최대 날짜 또는 최신 날짜를 선택하십시오.

다음은 두 개의 테이블입니다.

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; 

SQL Fiddle with Demo

또는 창 함수 는 가장 최근의 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; 

SQL Fiddle with Demo

이 쿼리는 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 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가 잘못하고있는 일입니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다