2015-04-14 70 views
0

所以我現在有這樣的一個方式,我想它是這樣:選擇甲骨文的某些記錄與最新的日期

SELECT * FROM 
(SELECT 
e.*, 
ROW_NUMBER() OVER (partition by USER_ID order by COPIED_TIMESTAMP DESC) r 
FROM 
TABLE e) 
WHERE r = 1; 

這工作得很好,但如果表是大的,我覺得可能會有性能問題。我一直在尋找這樣的事情:

SELECT MAX(COPIED_TIMESTAMP), USER_ID 
       FROM TABLE 
       GROUP BY USER_ID 

這也適用,但有一種方式來顯示所有信息不只是時間戳和ID。我對SQL/Oracle查詢很陌生,在這個問題上有點遺憾。

+0

可能重複[?窗口功能SORT昂貴的,我們能夠克服它(http://stackoverflow.com/questions/24620405/window-functions-sort-costly -can-we-over-it) –

+0

你可以考慮給你的密鑰列(USER_ID,COPIED_TIMESTAMP)添加索引。 –

回答

0

返回行,其中not exists相同的ID與後來的時間戳:

SELECT USER_ID, COPIED_TIMESTAMP, other_column1, other_column2 
FROM TABLE t1 
WHERE NOT EXISTS (select 1 from table t2 
        where t1.user_id = t2.user_id 
        and t2.COPIED_TIMESTAMP > t1.COPIED_TIMESTAMP) 
+0

您正在掃描表格兩次。在性能方面如何更好? –

+0

這裏沒有保證,但我會試一試! – jarlh

1

但如果表是大的,我覺得可能會有性能問題。

我認爲分析查詢就好了,因爲它會只掃描一次表。如果需要,您可以創建索引以進一步優化其性能。

您的第二個查詢將只返回時間戳和user_id列,但是,當您需要其他列時,您將無論如何都會執行多於一個表掃描的。所以,這不是一個好主意。

如果您正在尋找其他選項,如不存在,它仍然需要多個表掃描。

讓我們看到一個小的測試案例:

分析查詢

SQL> EXPLAIN PLAN FOR SELECT * FROM 
    2 (SELECT e.*, 
    3 ROW_NUMBER() OVER (partition BY deptno order by hiredate DESC) r 
    4 FROM emp e 
    5 ) WHERE r = 1; 

Explained. 

SQL> 
SQL> SELECT * FROM TABLE(dbms_xplan.display); 

PLAN_TABLE_OUTPUT 
---------------------------------------------------------------------------------------- 
Plan hash value: 3291446077 

--------------------------------------------------------------------------------- 
| Id | Operation    | Name | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT   |  | 14 | 1400 |  3 (0)| 00:00:01 | 
|* 1 | VIEW     |  | 14 | 1400 |  3 (0)| 00:00:01 | 
|* 2 | WINDOW SORT PUSHED RANK|  | 14 | 518 |  3 (0)| 00:00:01 | 
| 3 | TABLE ACCESS FULL  | EMP | 14 | 518 |  3 (0)| 00:00:01 | 
--------------------------------------------------------------------------------- 


PLAN_TABLE_OUTPUT 
---------------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - filter("R"=1) 
    2 - filter(ROW_NUMBER() OVER (PARTITION BY "DEPTNO" ORDER BY 
       INTERNAL_FUNCTION("HIREDATE") DESC)<=1) 

17 rows selected. 

SQL> 

NOT EXISTS查詢

SQL> EXPLAIN PLAN FOR 
    2 SELECT * 
    3 FROM emp t1 
    4 WHERE NOT EXISTS (SELECT 1 FROM emp t2 
    5     WHERE t1.deptno = t2.deptno 
    6      and t2.hiredate > t1.hiredate); 

Explained. 

SQL> 
SQL> SELECT * FROM TABLE(dbms_xplan.display); 

PLAN_TABLE_OUTPUT 
---------------------------------------------------------------------------------------- 
Plan hash value: 3353202012 

--------------------------------------------------------------------------- 
| Id | Operation   | Name | Rows | Bytes | Cost (%CPU)| Time  | 
--------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |  |  1 | 48 |  6 (0)| 00:00:01 | 
|* 1 | HASH JOIN ANTI |  |  1 | 48 |  6 (0)| 00:00:01 | 
| 2 | TABLE ACCESS FULL| EMP | 14 | 518 |  3 (0)| 00:00:01 | 
| 3 | TABLE ACCESS FULL| EMP | 14 | 154 |  3 (0)| 00:00:01 | 
--------------------------------------------------------------------------- 


PLAN_TABLE_OUTPUT 
---------------------------------------------------------------------------------------- 
Predicate Information (identified by operation id): 
--------------------------------------------------- 

    1 - access("T1"."DEPTNO"="T2"."DEPTNO") 
     filter("T2"."HIREDATE">"T1"."HIREDATE") 

16 rows selected. 

SQL> 

所以,你可以看到,解析查詢只做一個表掃描

0

Analytic functions是你的朋友:

SELECT MAX(COPIED_TIMESTAMP) KEEP (DENSE_RANK LAST ORDER BY COPIED_TIMESTAMP) AS COPIED_TIMESTAMP, 
     MAX(other_column ) KEEP (DENSE_RANK LAST ORDER BY COPIED_TIMESTAMP) AS other_column, 
     MAX(other_column2 ) KEEP (DENSE_RANK LAST ORDER BY COPIED_TIMESTAMP) AS other_column2, 
     USER_ID 
FROM TABLE_NAME 
GROUP BY USER_ID