2016-12-20 2 views
6

는 다음과 같은 두 개의 테이블을 고려JPA Criteria API의 Subquery에서 ORDER BY를 사용하는 대안은 무엇입니까?

  1. Project (id, project_name)
  2. StatusProject가되어있는 모든 상태를 포함
  3. Status (id, id_project, status_name)

.

최신 상태가 "new"인 모든 프로젝트를 쿼리하려고합니다. 내가 가지고 올 SQL 쿼리입니다 : 내가 기준 API를 사용하여 위의 쿼리를 복제하기 위해 노력하고있어 나는 클래스 CriteriaQuery이 방법 orderBy을 가지고 있지만 클래스 Subquery하지 않는 것으로 나타났습니다

SELECT q.id_project FROM status q 
WHERE q.status_name like 'new' 
AND q.id IN (
    SELECT TOP 1 sq.id from status sq 
    WHERE q.id_project = sq.id_project 
    ORDER BY sq.id DESC) 

.

지금까지 마련이다 한 기준 쿼리 : Subquery sq 그 결과를 정렬 및 최신 하나를 반환하기위한 어떤 방법이 없기 때문에 내가 여기에 붙어있어

CriteriaQuery<Project> q = criteriaBuilder.createQuery(Project.class); 
Root<Status> qFrom  = q.from(Status.class); 
Subquery<Integer> sq  = q.subquery(Integer.class); 
Root<Status> sqFrom  = sq.from(Status.class); 

sq.select(sqFrom.get(Status_.id)) 
    .where(criteriaBuilder.equal(sqFrom.get(Status_.project), qFrom.get(Status_.project)) 

.

위에서 설명한 시나리오에서 원하는 결과를 얻으려면 하위 쿼리를 정렬하는 대신 어떤 방법을 사용할 수 있습니까?

+0

가 문자열 기반 JPQL 허용하지 않습니다 상관되지 않은 형태로 집계 함수와 하위 쿼리, 그래서 나는 상관 하위 쿼리를 작성하는 것은 명시 적으로 성능 현명한 (예 JPQL를 사용하여 아래 기준 API 동등한은 간단합니다) 더 낫다고 생각한다 ORDER BY는 하위 쿼리에서 사용되며 Criteria는이를 간단히 나타냅니다. "subquery :: = simple_select_clause subquery_from_clause [where_clause] [groupby_clause] [having_clause]" –

+0

@NeilStockton 나는 대체 솔루션 –

+0

을 요청하는 이유 때문에 "sq.id"의 가장 높은 값을 하위 쿼리 (where 절을 준수)? "SELECT MAX (sq.id) FROM status sq WHERE q.id_project = sq.id_project"하위 쿼리를 수행 할 수 있습니까? –

답변

2

에서 추측에는 요 최대 값을 찾는 것. 이미 게시 된 것처럼 CriteriaQuery로 변환 할 수 있습니다.

불행하게도 기준 쿼리는 서브 쿼리에서 순서를 지원하지 않습니다 -이 관련 답변 참조 : 당신이 정말ORDER BY 필요한 경우

https://stackoverflow.com/questions/19549616#28233425 https://stackoverflow.com/questions/5551459#5551571

대안을 (예를 들어,) 아래의 예에서 값의 범위를 허용하는 대신 CriteriaQuery의 기본 쿼리를 사용하는 것입니다 : 다른 답변에 추가

Query query = entityManager.createNativeQuery(
    "SELECT bar FROM foo WHERE bar IN (SELECT TOP 10 baz FROM quux ORDER BY quuux)"); 
2

귀하의 하위 쿼리, 당신이 그것을 언급 한대로,

SELECT MAX(sq.id) FROM status sq WHERE q.id_project = sq.id_project 

의 JPQL에 달합니다는 완전히 JPA 스펙에 의해 지원되어야한다. 모든 레코드를 주문할 비해 느린로

SELECT q.id_project FROM status q 
WHERE q.status_name like 'new' 
AND q.id = (
    SELECT MAX(sq.id) from status sq 
    WHERE q.id_project = sq.id_project) 

이도 빠른 것 : 기준 API의 측면에서, 나는 SELECT MAX 대신 SELECT TOP 1 ... ORDER BY ...의 사용 하위 쿼리를 기록 할 수있는이

Subquery<Integer> sq  = q.subquery(Integer.class); 
Root<Status> sqFrom  = sq.from(Status.class); 
Expression maxExpr = criteriaBuilder.max(sqFrom.get(Status_.id)); 
sq.select(maxExpr).where(criteriaBuilder.equal(sqFrom.get(Status_.project), qFrom.get(Status_.project)) 
1

을, 나는 데이터베이스 최적화 암시 적 상관 관계를 다시 할 수 있다고 생각하지 않는다

select q.project from Status q 
where q.name = 'new' 
    and q.id in (select max(sq.id) from Status sq group by sq.project.id)