Chọn trong đó có ngày tối đa hoặc ngày mới nhất


15

Đây là hai bảng.

TRƯỜNG HỌC

SCHOOL_CODE + STAFF_TYPE_NAME + LAST_UPDATE_DATE_TIME + PERSON_ID
=================================================================
ABE           Principal         24-JAN-13               111222
ABE           Principal         09-FEB-12               222111

Con người

PERSON_ID + NAME
=================
111222      ABC
222111      XYZ

Đây là câu hỏi tiên tri của tôi.

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;

mang lại kết quả này

LAST_UPDATE SCHOOL_CODE PERSON_ID
===========+===========+=========
24-JAN-13   ABE         111222
09-FEB-12   ABE         222111

Tôi muốn chọn cái đầu tiên cho trường có ngày gần nhất.

Cảm ơn.

Câu trả lời:


28

Truy vấn hiện tại của bạn không cho kết quả mong muốn vì bạn đang sử dụng GROUP BYmệnh đề trên PERSON_IDcột có giá trị duy nhất cho cả hai mục nhập. Kết quả là bạn sẽ trả lại cả hai hàng.

Có một vài cách mà bạn có thể giải quyết điều này. Bạn có thể sử dụng truy vấn con để áp dụng hàm tổng hợp để trả về max(LAST_UPDATE_DATE_TIME)cho mỗi 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;

Xem SQL Fiddle với bản demo

Hoặc bạn có thể sử dụng chức năng cửa sổ để trả về các hàng dữ liệu cho từng trường gần đây nhất 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;

Xem SQL Fiddle với bản demo

Truy vấn này thực hiện việc row_number()gán một số duy nhất cho mỗi hàng trong phân vùng SCHOOL_CODEvà được đặt theo thứ tự giảm dần dựa trên LAST_UPDATE_DATE_TIME.

Là một lưu ý phụ, THAM GIA với chức năng tổng hợp không hoàn toàn giống với row_number()phiên bản. Nếu bạn có hai hàng có cùng thời gian sự kiện, THAM GIA sẽ trả về cả hai hàng, trong khi đó hàng row_number()sẽ chỉ trả về một hàng. Nếu bạn muốn trả về cả hai với chức năng cửa sổ, thì hãy xem xét sử dụng rank()chức năng cửa sổ thay vì nó sẽ trả về các mối quan hệ:

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;

Xem bản demo


4

Tôi ngạc nhiên không ai tận dụng các chức năng của cửa sổ ngoài row_number ()

Đây là một số dữ liệu để chơi với:

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');

Mệnh đề OVER () tạo một cửa sổ mà bạn sẽ xác định các nhóm tổng hợp của mình. Trong trường hợp này, tôi chỉ phân vùng trên SHOOL_CODE, vì vậy chúng ta sẽ thấy FIRST_VALUE, sẽ đến từ LAST_UPDATE_DATE_TIME, được nhóm bởi SCHOOL_CODE và theo thứ tự LAST_UPDATE_DATE_TIME theo thứ tự giảm dần. Giá trị này sẽ được áp dụng cho toàn bộ cột cho mỗi SCHOOL_CODE.

Điều quan trọng là phải chú ý đến phân vùng và thứ tự của bạn trong mệnh đề 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

Trả về:

24-JAN-13   ABE 111222

Điều này sẽ loại bỏ nhu cầu của bạn đối với NHÓM THEO và các truy vấn con trong hầu hết các phần. Bạn sẽ muốn đảm bảo bao gồm 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
Thay vì chỉ đăng mã, bạn nên cố gắng giải thích cách trả lời câu hỏi này; và có khả năng những gì OP đã làm không chính xác.
Max Vernon
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.