select the most recent entry

╄→гoц情女王★ 提交于 2019-12-23 03:59:12

问题


I have the following table:

LOCATION_ID, PERSON_ID, DATE
3, 65, 2016-06-03
7, 23, 2016-10-28
3, 23, 2016-08-05
5, 65, 2016-07-14

I want to build a select query in PL/SQL to select the records with the most recent location_id per person_id. For the above sample, the desired result should be:

LOCATION_ID, PERSON_ID, DATE
5, 65, 2016-07-14
7, 23, 2016-10-28

(DATE expressed as 'YYYY-MM-DD')

Thank you!


回答1:


The other proposals are correct but the most compact and fastest solution is most likely when you use FIRST_VALUE and LAST_VALUE Analytic Functions

SELECT DISTINCT
   FIRST_VALUE(LOCATION_ID) OVER (PARTITION BY PERSON_ID ORDER BY THE_DATE 
             ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS LOCATION_ID, 
   PERSON_ID, 
   MAX(THE_DATE) OVER (PARTITION BY PERSON_ID) AS LAST_DATE
FROM YOUR_TABLE;

Other people prefer

SELECT 
   MAX(LOCATION_ID) KEEP (DENSE_RANK FIRST ORDER BY DATE) as LOCATION, 
   PERSON_ID, 
   MAX(DATE) as LAST_DATE
FROM YOUR_TABLE
GROUP BY PERSON_ID;

which does the same, but I am not so familiar with this clause. See aggregate_function KEEP




回答2:


You can first extract the most recent event for each person by grouping results by PERSON_ID and selecting the MAX(DATE).

Then join the table with itself on those two columns to retrieve the LOCATION_ID

SELECT
  YOUR_TABLE.LOCATION_ID,
  YOUR_TABLE.PERSON_ID,
  YOUR_TABLE.DATE
FROM
  (SELECT
    PERSON_ID, MAX(DATE) AS max_date
  FROM
    YOUR_TABLE
  GROUP BY
    PERSON_ID
  ) AS t1
LEFT JOIN
  YOUR_TABLE
ON
  YOUR_TABLE.PERSON_ID = t1.PERSON_ID
  AND
  YOUR_TABLE.DATE = t1.max_date

By the way, you should not use reserved words like DATE for column names.

Here is fiddle to show it working: http://sqlfiddle.com/#!9/efdcb/2




回答3:


@quasoft is correct. Another way to deal with these kinds of GROUP BY problems (when you want to return more column than what you want to group by. In your case, you need to return location_id, person_id. But you only need to group by person_id), is to use analytical functions.

--schema:
CREATE TABLE my_table 
  ( 
     location_id NUMBER, 
     person_id   NUMBER, 
     date_       DATE 
  ); 

INSERT ALL 
INTO my_table 
VALUES (3, 65, To_date('2016-06-03', 'YYYY-MM-DD')) 
INTO my_table 
VALUES (7, 23, To_date('2016-10-28', 'YYYY-MM-DD')) 
INTO my_table 
VALUES (3, 23, To_date('2016-08-05', 'YYYY-MM-DD')) 
INTO my_table 
VALUES (5, 65, To_date('2016-07-14', 'YYYY-MM-DD')) 
SELECT * 
FROM   dual; 

--query:
WITH ordered 
     AS (SELECT location_id, 
                person_id, 
                date_, 
                Row_number() 
                  over ( 
                    PARTITION BY person_id 
                    ORDER BY date_ DESC) RN 
         FROM   my_table) 
SELECT location_id, 
       person_id, 
       date_ 
FROM   ordered 
WHERE  rn = 1; 

The query ordered sort your rows for each group by date. The main query, returns the first 1 of each group after it is sorted. Hence, it will return the in this case the last one (we ordered by date_ desc).




回答4:


This might work!

SELECT * FROM Your_Table A
JOIN (SELECT PERSON_ID,MAX(DATE) as MaxDate FROM Your_Table 
GROUP BY PERSON_ID) B
ON A.PERSON_ID = B.PERSON_ID AND A.DATE = B.MaxDate


来源:https://stackoverflow.com/questions/40435326/select-the-most-recent-entry

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!