최대 날짜 또는 최신 날짜를 가진 것을 선택하십시오


15

다음은 두 테이블입니다.

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

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

최신 날짜를 가진 학교의 첫 번째 학교를 선택하고 싶습니다.

감사.

답변:


28

두 항목에 대해 고유 한 값을 가진 열에 GROUP BY절을 사용하고 있으므로 현재 쿼리에서 원하는 결과를 제공하지 않습니다 PERSON_ID. 결과적으로 두 행을 모두 반환합니다.

이 문제를 해결할 수있는 몇 가지 방법이 있습니다. 하위 쿼리를 사용하여 집계 함수를 적용하여 max(LAST_UPDATE_DATE_TIME)각각에 대해 를 반환 할 수 있습니다 SCHOOL_CODE.

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 참조

또는 창 기능 을 사용하여 가장 최근에 각 학교의 데이터 행을 반환 할 수 있습니다 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 참조

이 쿼리 row_number()는 파티션의 각 행에 고유 번호를 할당 SCHOOL_CODE하고LAST_UPDATE_DATE_TIME .

참고로 집계 함수가있는 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;

데모 보기


4

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가 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를 포함시켜야합니다.


1
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)

1
코드 게시하는 대신 이것이 질문에 어떻게 대답하는지 설명해야합니다. 잠재적으로 OP가 잘못하고있는 것.
Max Vernon
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.