Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@


import java.time.LocalDate;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.ezcode.codetest.domain.submission.dto.DailyCorrectCount;
import org.ezcode.codetest.domain.submission.model.entity.QUserProblemResult;
import org.springframework.stereotype.Repository;

import com.querydsl.core.group.GroupBy;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;

Expand All @@ -29,24 +29,38 @@ public List<DailyCorrectCount> countCorrectByUserGroupedByDate(Long userId) {
QUserProblemResult upr = QUserProblemResult.userProblemResult;

var date = Expressions.dateTemplate(LocalDate.class, "DATE({0})", upr.modifiedAt);
NumberExpression<Long> countDistinctProblem = upr.problem.id.countDistinct();

return queryFactory
var results = queryFactory
.select(
date,
upr.problem.id.countDistinct(),
upr.problem.id
)
.from(upr)
Comment on lines +32 to 38
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

집계 함수와 비집계 컬럼 동시 선택으로 JPQL/SQL 오류 위험이 큽니다.

GROUP BY 없이 countDistinct()date, problem.id를 함께 select하면 JPQL 규약 위반이며, 다수 DB에서 실행 오류가 납니다. 수기 그룹핑으로 갈 거라면 집계를 쿼리에서 제거해야 합니다.

아래 최소 수정으로 집계 컬럼을 제거하세요(아래 인덱스 수정은 다음 코멘트 참조).

-        var results = queryFactory
-            .select(
-                date,
-                upr.problem.id.countDistinct(),
-                upr.problem.id
-            )
+        var results = queryFactory
+            .select(
+                date,
+                upr.problem.id
+            )
             .from(upr)
             .where(
                 upr.user.id.eq(userId),
                 upr.isCorrect.eq(true)
             )
             .orderBy(date.asc())
             .fetch();

Also applies to: 44-44

.where(
upr.user.id.eq(userId),
upr.isCorrect.eq(true)
)
.orderBy(date.asc())
.transform(
GroupBy.groupBy(date).list(
Projections.constructor(
DailyCorrectCount.class,
date,
countDistinctProblem,
GroupBy.set(upr.problem.id)
)
)
);
.fetch();

// 결과를 수동으로 그룹화해야함
Map<LocalDate, Set<Long>> problemIdsByDate = new LinkedHashMap<>();
Map<LocalDate, Long> countsByDate = new LinkedHashMap<>();

for (var result : results) {
LocalDate resultDate = result.get(0, LocalDate.class);
Long problemId = result.get(2, Long.class);

problemIdsByDate.computeIfAbsent(resultDate, k -> new HashSet<>()).add(problemId);
countsByDate.put(resultDate, (long) problemIdsByDate.get(resultDate).size());
}
Comment on lines +48 to +56
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

선택 컬럼 인덱스 불일치 및 불필요한 countsByDate 유지.

위 수정으로 select 컬럼이 2개가 되므로 result.get(2, ...)는 범위 밖 접근이 됩니다. 또한 countsByDateSet 크기에서 항상 유도 가능해 중복입니다.

아래처럼 인덱스와 반환 구성을 정리하세요.

-        Map<LocalDate, Long> countsByDate = new LinkedHashMap<>();
-        
-        for (var result : results) {
-            LocalDate resultDate = result.get(0, LocalDate.class);
-            Long problemId = result.get(2, Long.class);
-            
-            problemIdsByDate.computeIfAbsent(resultDate, k -> new HashSet<>()).add(problemId);
-            countsByDate.put(resultDate, (long) problemIdsByDate.get(resultDate).size());
-        }
-        
-        return problemIdsByDate.entrySet().stream()
-            .map(entry -> new DailyCorrectCount(
-                entry.getKey(),
-                countsByDate.get(entry.getKey()),
-                entry.getValue()
-            ))
-            .collect(Collectors.toList());
+        for (var result : results) {
+            LocalDate resultDate = result.get(0, LocalDate.class);
+            Long problemId = result.get(1, Long.class);
+            problemIdsByDate
+                .computeIfAbsent(resultDate, k -> new HashSet<>())
+                .add(problemId);
+        }
+
+        return problemIdsByDate.entrySet().stream()
+            .map(entry -> new DailyCorrectCount(
+                entry.getKey(),
+                (long) entry.getValue().size(),
+                entry.getValue()
+            ))
+            .collect(Collectors.toList());

Also applies to: 58-64

🤖 Prompt for AI Agents
In
src/main/java/org/ezcode/codetest/infrastructure/persistence/repository/submission/query/UserProblemResultQueryRepositoryImpl.java
around lines 48-56 (and similarly 58-64), the loop uses result.get(2,
Long.class) but the SELECT now returns only two columns so index 2 is out of
range and countsByDate is redundant; change to use the correct column index for
problemId (likely result.get(1, Long.class) or the second selected column),
remove the countsByDate map entirely, update the loop to only populate
problemIdsByDate (computeIfAbsent(...).add(problemId)), and when you need counts
derive them from problemIdsByDate.get(date).size() rather than maintaining a
separate map; apply the same index and removal fix to the code at lines 58-64.


return problemIdsByDate.entrySet().stream()
.map(entry -> new DailyCorrectCount(
entry.getKey(),
countsByDate.get(entry.getKey()),
entry.getValue()
))
.collect(Collectors.toList());
}
}