DB

[Prisma] sum 구하기 - groupby 사용법

developerYoung 2023. 11. 28. 23:07
반응형

안녕하세요. 항상 유익한 정보를 제공하기 위해 글을 쓰려고 노력하는 웹개발자입니다!

 

오늘은 지난 시간에 다뤘던 Prisma의 aggregate에 이어서 groupby를 사용해보려 해요

프로젝트에 적용할 통계 데이터 합산을 위한 로직이 필요하여 적용할겸 정리할겸 다뤄보려합니다 ㅎㅎ

 

Groupby 사용법

groupby가 무엇인지 잘 모르는 분을 위해서 간단히 설명하자면, 특정 group을 기준으로 데이터를 묶는 방법입니다.

 

예를들어 다음과 같은 데이터가 있다고 해볼게요.

a 1
a 2
b 5
c 4
c 6

 

이 데이터에서 같은 문자끼리 묶어서 총합을 구하고 싶다면 a = 1 + 2, b = 5, c = 4 + 6 이 되겠죠!

이렇게 특정한 group을 만들어 계산하게 도와주는 방법이 groupby 이에요.

 

prisma 문서를 보시면 이렇게 설명해요.

Prisma Client's groupBy allows you to group records by one or more field values - such as country, or country and city and perform aggregations on each group, such as finding the average age of people living in a particular city.

 

record를 하나 또는 여러개의 field로 그룹을 만들어 그룹별로 aggregation을 하는 것 이라고 해요.

 

간단히 prisma 공식문서의 사용법을 보여드릴게요!

 

그럼 이제 어떠한 속성이 있는지 알아볼까요?

다음과 같은 option들을 이용해 통계를 구할 수 있어요.

options description
where 말그대로 SQL의 WHERE 절
by group할 field string or string[]
having 계산값 조건절 SQL의 HAVING
_count 조건에 맞는 개수를 리턴
_avg 조건에 맞는 데이터의 평균
_sum 조건에 맞는 데이터의 합산
_min 조건에 맞는 데이터 중 최소
_max 조건에 맞는 데이터 중 최대

 

Groupby 적용

그러면 본격적으로 사용법을 알아보도록 할게요! 1차 관계에서의 sum 먼저 구현해보도록 할게요!

먼저 prisma.[schema명].groupby를 통해 작성하고, _sum 옵션을 사용해보세요!

const userData = await prisma.userDataDetail.groupBy({
  by: ['chapterId'],
  _sum: {
    correctCnt: true,
    wrongCnt: true,
  },
});
 
 
 // Schema Model
model UserDataDetail {
  userDataDetailId Int      @id @default(autoincrement()) @map("user_data_detail_id")
  userData         UserData @relation(fields: [userDataId], references: [userDataId])
  userDataId       Int      @map("user_data_id")
  chapterId        Int      @map("chapter_id")
  chapter          Chapter? @relation(fields: [chapterId], references: [chapterId])
  correctCnt       Int      @default(0) @map("correct_cnt")
  wrongCnt         Int      @default(0) @map("wrong_cnt")

  @@map("user_data_detail")
}

 

위와 같이 groupBy 로직을 해석하면 어떻게 될까요?!

 

=> by 를 통한 chapterId를 그룹으로 묶은 후에 correctCnt와 wrongCnt의 sum을 구하는 과정이 됩니다! (같은 chapterId들의 합산 리스트를 리턴)

 

prisma groupby 결과

 

 

위의 사진과 같이 같은 chapterId들을 묶어서 _sum의 결과를 보여주는것을 알 수 있어요!

같은 원리를 통해 _avg, _count, _min 등도 직접 구해보면서 연습해보면 좋을거에요ㅎㅎ

 

2차 Relation GroupBy

사실 제가 sum을 구하려했던 목적은 2차 관계에서 prisma는 어떻게 sum을 적용할지 입니다.. ㅠㅠ

prisma에서 orm 구성을 적용하기 쉽게 짜셨다면, 어렵지 않게 groupBy를 성공할 수 있어요.

 

저의 관계는 UserData -> UserDataDetail 의 연관관계로 아래 모델에서 확인할 수 있어요!

저는 subjectId를 통해 하위의 chapterId를 기반으로 하는 UserDataDetail의 groupBy를 하길 원했습니다.


model UserData {
  userDataId Int  @id @default(autoincrement()) @map("user_data_id")
  subjectId Int     @map("subject_id")
  
  userDataDetail UserDataDetail[]

  @@map("user_data")
}

model UserDataDetail {
  userDataDetailId Int      @id @default(autoincrement()) @map("user_data_detail_id")
  userData         UserData @relation(fields: [userDataId], references: [userDataId])
  userDataId       Int      @map("user_data_id")
  chapterId        Int      @map("chapter_id")
  correctCnt       Int      @default(0) @map("correct_cnt")
  wrongCnt         Int      @default(0) @map("wrong_cnt")

  @@map("user_data_detail")
}

 

 

먼저 결과를 보기 전에 다시 어떻게 조회할지 생각해보면요.

UserData와 UserDataDetail 1:N 관계로 UserData에 있는 subjectId로 UserDataDetail의 chapterId 마다의 총 correctCnt와 wrongCnt의 합을 구해야합니다!

 

역시 prisma 너무 간단하게 where절에서 userData와 연관된 subjectId로 데이터를 조회하여 _sum 옵션만 사용하면 끝나게 됩니다!

const userData = await prisma.userDataDetail.groupBy({
  where: { userData: { subjectId: Number(subjectId) } },
  by: ['chapterId'],
  _sum: {
    correctCnt: true,
    wrongCnt: true,
  },
});

 

결과도 깔끔하게 나오게 됩니다! (사실 위에서 보여드렸던 사진이,,, 이 쿼리의 결과입니다 ㅎㅎ..)

 

 

 

이상으로 오늘의 내용은 마치고 또 다시 공부하는 내용이 생기면 찾아오도록 할게요~!

반응형

'DB' 카테고리의 다른 글

[Prisma] sum 구하기 - aggregate 사용법  (0) 2023.11.27