다음은 두 개의 테이블입니다.
SCHOOL_STAFF
SCHOOL_CODE + STAFF_TYPE_NAME + LAST_UPDATE_DATE_TIME + PERSON_ID ================================================================= ABE Principal 24-JAN-13 111222 ABE Principal 09-FEB-12 222111
PERSONS
PERSON_ID + NAME ================= 111222 ABC 222111 XYZ
여기 내 오라클 쿼리입니다.
SELECT MAX(LAST_UPDATE_DATE_TIME) AS LAST_UPDATE, SCHOOL_CODE, PERSON_ID FROM SCHOOL_STAFF WHERE STAFF_TYPE_NAME="Principal" GROUP BY SCHOOL_CODE, PERSON_ID ORDER BY SCHOOL_CODE;
이 결과를 제공합니다
LAST_UPDATE SCHOOL_CODE PERSON_ID ===========+===========+========= 24-JAN-13 ABE 111222 09-FEB-12 ABE 222111
최신 날짜가있는 학교의 첫 번째 학교를 선택하고 싶습니다.
감사합니다.
답변
GROUP BY
<를 사용하고 있기 때문에 현재 검색어가 원하는 결과를 제공하지 않습니다. 두 항목에 대해 고유 한 값이있는 PERSON_ID
열의 / div> 절. 결과적으로 두 행을 모두 반환합니다.
이 문제를 해결할 수있는 몇 가지 방법이 있습니다. 하위 쿼리를 사용하여 집계 함수를 적용하여 각 SCHOOL_CODE
에 대해 max(LAST_UPDATE_DATE_TIME)
를 반환 할 수 있습니다.
select s1.LAST_UPDATE_DATE_TIME, s1.SCHOOL_CODE, s1.PERSON_ID from SCHOOL_STAFF s1 inner join ( select max(LAST_UPDATE_DATE_TIME) LAST_UPDATE_DATE_TIME, SCHOOL_CODE from SCHOOL_STAFF group by SCHOOL_CODE ) s2 on s1.SCHOOL_CODE = s2.SCHOOL_CODE and s1.LAST_UPDATE_DATE_TIME = s2.LAST_UPDATE_DATE_TIME;
또는 창 함수 는 가장 최근의 LAST_UPDATE_DATE_TIME
를 사용하여 각 학교에 대한 데이터 행을 반환합니다.
select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME from ( select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME, row_number() over(partition by SCHOOL_CODE order by LAST_UPDATE_DATE_TIME desc) seq from SCHOOL_STAFF where STAFF_TYPE_NAME="Principal" ) d where seq = 1;
이 쿼리는 row_number()
는 SCHOOL_CODE
파티션의 각 행에 고유 번호를 할당하고
.
참고로, 집계 함수가있는 JOIN은 row_number()
버전과 정확히 동일하지 않습니다. 이벤트 시간이 같은 두 개의 행이있는 경우 JOIN은 두 행을 모두 반환하지만 row_number()
는 하나만 반환합니다. 윈도우 기능으로 둘 다 반환하려면 rank()
윈도우 기능을 사용하는 것이 좋습니다. 대신 타이를 반환합니다.
select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME from ( select SCHOOL_CODE, PERSON_ID, LAST_UPDATE_DATE_TIME, rank() over(partition by SCHOOL_CODE order by LAST_UPDATE_DATE_TIME desc) seq from SCHOOL_STAFF where STAFF_TYPE_NAME="Principal" ) d where seq = 1;
댓글
보기
- 감사합니다. 하위 쿼리 테이블 (위의 예 1)에 대한 내부 조인은 가장 직관적이며 ' 분할 기준 이 무엇인지 알 필요가 없습니다. 약. 다음은 예제 1과 유사한 구문입니다. originalTable 에서 oT b로 oT.dateField, oT.siteID, oT.field1, oT.field2, oT.field3을 선택합니다. > inner join (select max (dateField) as newestDate, siteID from originalTable group by siteID) as newTable on oT.siteID = newTable.site_ID and oT.dateField = newTable.newestDate order by oT.siteID asc 나에게 더 잘 설명하는 내용 '가 하위 쿼리에서 발생합니다.
답변
I “누구도 row_number () 이외의 창 함수를 활용하지 않았다는 사실에 놀랐습니다.
다음은 재생할 데이터입니다.
CREATE TABLE SCHOOL_STAFF ( LAST_UPDATE_DATE_TIME VARCHAR(20), SCHOOL_CODE VARCHAR(20), PERSON_ID VARCHAR(20), STAFF_TYPE_NAME VARCHAR(20) ); INSERT INTO SCHOOL_STAFF VALUES ("24-JAN-13", "ABE", "111222", "Principal"); INSERT INTO SCHOOL_STAFF VALUES ("09-FEB-12", "ABE", "222111", "Principal");
OVER () 절은 집계 그룹을 정의 할 창을 만듭니다. 이 경우에는 SHOOL_CODE에서만 파티션을 나누고 있으므로 FIRST_VALUE가 표시됩니다. FIRST_VALUE는 LAST_UPDATE_DATE_TIME에서 SCHOOL_CODE로 그룹화되고 내림차순으로 LAST_UPDATE_DATE_TIME 순서로 표시됩니다. 이 값은 각 SCHOOL_CODE의 전체 열에 적용됩니다.
over () 절에서 분할 및 순서에 세심한주의를 기울이는 것이 중요합니다.
SELECT DISTINCT FIRST_VALUE(LAST_UPDATE_DATE_TIME) OVER (PARTITION BY SCHOOL_CODE ORDER BY LAST_UPDATE_DATE_TIME DESC) AS LAST_UPDATE ,FIRST_VALUE(SCHOOL_CODE) OVER (PARTITION BY SCHOOL_CODE ORDER BY LAST_UPDATE_DATE_TIME DESC) AS SCHOOL_CODE ,FIRST_VALUE(PERSON_ID) OVER (PARTITION BY SCHOOL_CODE ORDER BY LAST_UPDATE_DATE_TIME DESC) AS PERSON_ID FROM SCHOOL_STAFF WHERE STAFF_TYPE_NAME = "Principal" ORDER BY SCHOOL_CODE
반환 :
24-JAN-13 ABE 111222
이렇게하면 GROUP BY 및 하위 쿼리가 필요하지 않습니다. 대부분. 그래도 DISTINCT를 포함하고 싶을 것입니다.
Comments
- 이것은 좋지만 over 절을 반복하지 않는 방법이 있습니다. 모든 열?
답변
select LAST_UPDATE_DATE_TIME as LAST_UPDATE, SCHOOL_CODE, PERSON_ID from SCHOOL_STAFF WHERE STAFF_TYPE_NAME="Principal" AND LAST_UPDATE_DATE_TIME = (SELECT MAX(LAST_UPDATE_DATE_TIME) FROM SCHOOL_STAFF s2 WHERE PERSON_ID = s2.PERSON_ID)
댓글
- 단지 코드를 게시하는 대신 질문에 대한 답변을 설명해야합니다. 그리고 잠재적으로 OP가 잘못하고있는 일입니다.