16

「DISTINCT ON」と「GROUP BY」を不適切に使用したために、データベース クエリが予期しない結果を返すことに気付きました。

誰かがこれについて私をまっすぐにしてくれることを願っています。実際のクエリは非常に複雑なので、簡単に説明します。

object_id とタイムスタンプで構成されるテーブル/内部クエリがあります。

CREATE TABLE test_select ( object_id INT , event_timestamp timestamp );
COPY test_select (object_id , event_timestamp) FROM stdin (DELIMITER '|');
1           | 2013-01-27 21:01:20
1           | 2012-06-28 14:36:26
1           | 2013-02-21 04:16:48
2           | 2012-06-27 19:53:05
2           | 2013-02-03 17:35:58
3           | 2012-06-14 20:17:00
3           | 2013-02-15 19:03:34
4           | 2012-06-13 13:59:47
4           | 2013-02-23 06:31:16
5           | 2012-07-03 01:45:56
5           | 2012-06-11 21:33:26
\.

逆クローンのタイムスタンプによって順序付け/重複排除された個別の ID を選択しようとしています

したがって、結果は [ 4, 1, 3, 2, 5 ] になります。

私はこれが私が必要とすることをすると思います(それはそうです):

SELECT object_id  
FROM test_select 
GROUP BY object_id 
ORDER BY max(event_timestamp) DESC
;

テスト/監査の目的で、タイムスタンプ フィールドを含めたい場合があります。そのクエリに別のフィールドを含める方法がわかりません。

上記の私のSQLの明白な問題、または監査情報を含める方法に関する提案を誰かが指摘できますか?

4

2 に答える 2

22

object_idand だけでなくすべての列を選択できるようにするにはMAX(event_timestamp)、次を使用できますDISTINCT ON

SELECT DISTINCT ON (object_id) 
    object_id, event_timestamp    ---, more columns
FROM test_select 
ORDER BY object_id, event_timestamp DESC ;

event_timestamp DESC結果を ではなく で並べ替えたい場合object_idは、それを派生テーブルまたは CTE に含める必要があります。

SELECT *
FROM 
  ( SELECT DISTINCT ON (object_id) 
        object_id, event_timestamp    ---, more columns
    FROM test_select 
    ORDER BY object_id, event_timestamp DESC 
  ) AS t
ORDER BY event_timestamp DESC ;

または、次のようなウィンドウ関数を使用できますROW_NUMBER()

WITH cte AS
  ( SELECT ROW_NUMBER() OVER (PARTITION BY object_id 
                              ORDER BY event_timestamp DESC) 
             AS rn, 
           object_id, event_timestamp    ---, more columns
    FROM test_select 
  )
SELECT object_id, event_timestamp    ---, more columns
FROM cte
WHERE rn = 1
ORDER BY event_timestamp DESC ;

または集約MAX():OVER

WITH cte AS
  ( SELECT MAX(event_timestamp) OVER (PARTITION BY object_id) 
             AS max_event_timestamp, 
           object_id, event_timestamp    ---, more columns
    FROM test_select 
  )
SELECT object_id, event_timestamp    ---, more columns
FROM cte
WHERE event_timestamp = max_event_timestamp
ORDER BY event_timestamp DESC ;
于 2013-09-22T01:46:50.967 に答える