복붙노트

[SQL] 각 항목에 대한 JPA 선택 최신 인스턴스

SQL

각 항목에 대한 JPA 선택 최신 인스턴스

하자 내가 회의 실체를 말한다. 각 회의는 한 참석자와 회의 날짜가 있습니다. 내 회의 테이블 내에서 I는 각각 다른 날짜에 각 참석자에 대해 여러 모임을 가질 수있다. 나는 모든 참석자에 대한 최신 회의를 선택하는 JPA 쿼리가 필요합니다. 예를 들어, 내 표는 다음과 같습니다 경우

Meeting ID | Attendee ID | Meeting Date
1          | 1           |  6/1/2011
2          | 2           |  6/1/2011
3          | 1           |  6/6/2011
4          | 3           |  6/6/2011

내 결과는해야한다

Meeting ID | Attendee ID | Meeting Date
2          | 2           |  6/1/2011
3          | 1           |  6/6/2011
4          | 3           |  6/6/2011

포스트 그레스에 대한 JPA (2)를 사용. 회의 참석자 및 간단한 타임 스탬프 날짜에 1-1 있습니다. 나는하여 그룹을 할 필요 및 최대 (ㅋ ㅋ)에 갈거야 어쩌면 자신에 가입 의심하지만,이 접근하는 나는 최선의 방법을 모르겠어요.

최신 정보: 이 함께 저녁 연주를 지출 후, 나는 아직도이에 허용 JPQL 솔루션이 없습니다. 여기에 지금까지 무엇을 가지고 :

select m from Meeting m 
where m.meetingDate in 
    ( select max(meet.meetingDate) 
      from Meeting meet group by meet.attendee )

나는 참석자 부서 및 이것 저것에 의해 필터링처럼,이 질문에 관련이없는 다양한 조건을 가지고있다. 우리가 회의 번째 (또는 미세한)에 날짜와 정확히 같은 시간이 최소 두 개의 모임이있을 것이라는 가능성을 추적하기 때문에이 작품 유일한 이유입니다. 우리는 경우에 각 참석자 만 했나 마지막 회의를 유지하기 위해 주위 일부 자바 물건을 가하고 있습니다 우리가 같은 시간에 두 가지를 얻을 수 없지만, 아주 시시한 솔루션의 그. 정말 모든 쿼리에 그걸 얻기 위해 너무 어렵지 않을해야하지만, 나는 그것을 알아 내기 위해 아직있다.

갱신 2 : 내가보기를 만들 SQL을 사용하고 난 그와 함께 확인 해요 뷰에 매핑하는 JPA 객체를 생성해야하는 경우 때문에 SQL 태그를 추가.

해결법

  1. ==============================

    1.나는이 쿼리를 가지고 생각합니다.

    나는이 쿼리를 가지고 생각합니다.

    select m from Meeting m 
        where m.meetingDate = 
            (select max(m1.meetingDate) 
                from Meeting m1 
                where m1.attendee = m.attendee )
        and not exists 
            (select m2 from Meeting m2 
                where m2.attendee = m.attendee 
                and m2.meetingDate > m.meetingDate)
    
  2. ==============================

    2.SQL에서이 솔루션은 매우 간단합니다 - 당신에게 각 참석자에 대한 가장 최근의 회의를 제공하는 하위 쿼리와 테이블을 조인

    SQL에서이 솔루션은 매우 간단합니다 - 당신에게 각 참석자에 대한 가장 최근의 회의를 제공하는 하위 쿼리와 테이블을 조인

    select * from Meeting ALL
    join ( select max(meetingDate) as newest, attendee
    from Meeting group by attendee ) LATEST
    on ALL.meetingDate = LATEST.newest AND ALL.attendee = LATEST.attendee
    

    이 작품, 빠르게 작동합니다!

    JPA의 문제는 조인을 위해 (또는 대부분의 구현)는 하위 쿼리를 허용하지 것입니다. 다음 처음부터 컴파일하고 무슨하려고 몇 시간을 소비 한 후, 그것이 얼마나 느린, 내가 JPA를 싫어했다. 것과 같은 솔루션은 위 - EXISTS처럼 (.. SELECT) 또는은 (SELECT는 ..) - 테이크 세 느린 그들이해야보다 크기의 명령을 실행 할 수 있습니다.

    난 그냥 JPA에서 솔루션이 액세스하는 데 필요한 것을 의미 작동하는 솔루션을 가졌어요. 도움 당신은 그냥 그렇게하는 것이 SQL에 두 개의 마법의 단어가 있습니다 :

    CREATE VIEW
    

    생명은 바로 그러한 주체를 정의하고 그것을 사용 ... 그래서 훨씬 간단해진다. 주의 :이있어 읽기 전용입니다.

    당신이 그렇게 할 때 물론, 어떤 JPA 순수 주의자는 사람이 순수한 JPA 솔루션을 제공 그렇다면, 우리 모두 알려주세요, 당신을 내려다 볼 것이다!

  3. ==============================

    3.나는 그 JPA에 매핑 할 수 있습니다 가정 있도록 잘 SQL에서, 내가 생각하는 매우 간단 할 것이라고 :

    나는 그 JPA에 매핑 할 수 있습니다 가정 있도록 잘 SQL에서, 내가 생각하는 매우 간단 할 것이라고 :

    SELECT m.AttendeeId, MAX(m.MeetingDate) from Meeting m GROUP BY m.AttendeeId
    

    편집 : 당신은뿐만 아니라 messageId가 자신을해야 할 경우 간단한 하위 쿼리와 함께 그렇게 할 수 반환하는 다른 두 값이 같은 메시지에 대한 messageId가. 그냥 당신이 같은 참석자 및 날짜에 대한 몇 가지 messageIds가있는 경우를 처리 할 (그들은 모두 똑같이 잘해야하기 때문에 예를 들어 첫 번째 결과를 선택 - 내가 그와 같은 데이터를 의심 거라고하지만, 심지어 회의에 대한 의미가 있습니다)

  4. ==============================

    4.로 Bulba 적절한 방법에 의해 그룹과 하위 쿼리에 가입하는 것입니다 말했다.

    로 Bulba 적절한 방법에 의해 그룹과 하위 쿼리에 가입하는 것입니다 말했다.

    문제는 당신이 하위 쿼리에 가입 할 수 있다는 것입니다.

    여기에 해결 방법이 있습니다.

    당신은에 의해 그룹과 하위 쿼리의 내용물을 볼 수 있습니다. 당신은 쌍 (attendee_id, 최대 (meeting_date))의 목록을 얻을. 이 쌍은 당신이에 가입하려는 최대 날짜 행에 대해 새로운 고유 ID와 같다. 테이블의 각 행에 한쌍 (attendee_id, meeting_date)를 형성하도록 그 다음 주. 모든 행은 한 쌍 (attendee_id, meeting_date)와 같은 ID를 가지고 그래서. 단지 그것이 부질 수신 목록에 속하는 ID를 형성하는 경우 행을 할 수 있습니다.

    CONCAT (attendee_id, meeting_date) 간략 함을 위해 attendee_id meeting_date와의 연결 등이 ID 쌍을 나타낼 수 있습니다.

    그런 다음 다음과 같이 (유사 JPQL 및 JPA CriteriaBuilder에 대한) SQL의 쿼리는 다음과 같습니다

    SELECT * FROM meetings 
    WHERE concat(attendee_id, meeting_date) IN
    (SELECT concat(attendee_id, max(meeting_date)) FROM meetings GROUP BY attendee_id)
    

    쿼리 당 하나의 하위 쿼리, 일부 답변처럼 각 행에 대해 하나도 하위 쿼리가 있습니다.

    우리는 당신을위한 특별한 제안을 해!

    숫자 ID 쌍 그 인코딩을 할 수 있습니다. 그것은 attendee_id 및 meeting_date의 합이 될하지만 수정과 코드의 고유성을 보장하기 위해. 우리는 유닉스 시간과 날짜의 숫자 표현을 할 수 있습니다. 우리는 마지막 코드는 최대 값 제한이 있기 때문에 우리의 코드를 캡처 할 수있는 최대 날짜 (예를 들어, BIGINT (INT8) <263)의 값을 수정합니다. 2149년 6월 7일 3시 0분 0초 편의상 최대 날짜를 취할 수 있습니다. 이 일 초 5,662,310,400과 65,536 같습니다. 나는 (우리는 아래의 시간을 무시하고 그래서) 우리가 일 날짜에 대한 정밀도를 필요로 여기에 가정합니다. 고유 코드를 생성하기 위해 우리는 수치 시스템에서 65536의 기본 (216-1 0에서 수) 마지막으로 기호 나 코드로 숫자 시스템에 숫자로 해석 할 수는 일의 수입니다. 다른 기호 attendee_id 캡처합니다. 각 X는 범위 [0,216-1]에 XXXX 같은 이러한 해석 코드 모양을 (더 정확한 것으로, 제 X 인해 부호 1 비트 범위 [0,215-1]이다), 제 세 X attendee_id 성과를 나타내는 X는 meeting_date를 나타냅니다. attendee_id의 최대 값 그래서 우리의 코드 캔 캡처 247-1입니다. 이 코드는 attendee_id * 65536 + "일 날짜"로 계산 될 수있다.

    PostgreSQL의에서이 될 것입니다 :

    attendee_id*65536 + date_part('epoch', meeting_date)/(60*60*24)
    

    date_part 반환 우리는 일정에 나누어 일을 변환 초 날짜 곳.

    그리고 마지막 쿼리는 모든 참석자에 대한 최신 회의를 얻을 수 있습니다 :

    SELECT * FROM meetings
    WHERE attendee_id*65536 + date_part('epoch', meeting_date)/(60*60*24)
    IN (SELECT attendee_id*65536 + date_part('epoch', max(meeting_date))/(60*60*24) from meetings GROUP BY attendee_id);
    

    I 질문과 stucture있는 테이블을 만들고 100,000 행 무작위로 [10000] 및 범위에서 임의의 날짜 [1970-01-01, 2017년 9월 16일]에서 attendee_id를 선택로 채워져있다. 나는 다음과 같은 기술과 쿼리 (ANALYZE EXPLAIN과) 벤치마킹했다 :

    여기에 테이블 방식 (CSV로) 테이블 데이터, 테이블을 채우기위한 코드 및 쿼리와 자식입니다.

  5. ==============================

    5.이 시도

    이 시도

    SELECT MAX(m.MeetingDate) FROM Meeting m
    
  6. from https://stackoverflow.com/questions/6296347/jpa-select-latest-instance-for-each-item by cc-by-sa and MIT license