2016-11-05 84 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