2016-11-05 82 views
1

我下面的表格有:选择最新的条目

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 

我想建立在PL/SQL选择查询,选择与每为person_id的最近 LOCATION_ID记录。对于上述样品,所期望的结果应该是:

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

(DATE表示为 'YYYY-MM-DD')

谢谢!

+0

您是否检查过收到的所有答案?你把最没有效率的标记为“正确”。 Wernfried的第二个*解决方案显然是最好的。它只在整个表格上传递一次 - 没有连接,所以它比任何基于连接的解决方案都快得多。 Hawk的解决方案和Wernfried的第一个解决方案是第二好的解决方案(两次通过,但仍然没有加入,所以仍然快得多)。如果你不明白他们的解决方案,你可以**问**。 – mathguy

+0

我标记了“正确”的第一个答案,我阅读并为我工作。今天,我读了所有的答案。 –

回答

4

其他的建议是正确的,但最紧凑的,当你使用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; 

其他人更喜欢

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; 

它做同样的最快的解决方案是最有可能的,但我不这么熟悉这一条款。见aggregate_function KEEP

+0

第二种解决方案的偏好是合理的,因为它是正确的。它不会像第一个那样“相同”。第一个解决方案使用分析函数,因此结果将有与基表一样多的行(具有许多重复项)。您需要再次选择(或“分组”)或执行某项操作)以删除重复项。 – mathguy

+0

@mathguy,我在第一个查询中使用了DISTINCT。应该是正确的。 –

+0

哦,对不起,我没注意。从正确的答案来看,它是“正确的”,但如果表格很大,它可能是非常低效的。通常,当你必须使用“distinct”(明确地或隐藏在GROUP BY等中)这是一个迹象表明可能存在更好的解决方案。在这种情况下,它是 - 这是你的第二个解决方案。 – mathguy

1

您可以通过将结果分组为PERSON_ID并选择MAX(DATE)来首先提取每个人的最近事件。

然后加入自己对这两列的表检索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 

顺便说一句,你不应该使用保留字像DATE列名。

这里是小提琴展现它的工作:http://sqlfiddle.com/#!9/efdcb/2

+0

DATE名称只是为了介绍我的问题。感谢您指出这一点 –

0

@quasoft是正确的。处理这种GROUP BY问题的另一种方法(当你想返回比你想要分组更多的列时,你需要返回location_id,person_id但是你只需要通过person_id来分组)。使用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; 

查询ordered按日期对每个组进行排序。主查询返回每个组排序后的第一个。因此,它将在这种情况下返回最后一个(我们按date_desc命令)。

0

这可能工作!

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