2013-09-22 7 views
11

「BY GROUP」「DISTINCT ON」と私は、データベースのクエリは、私が誰かを願っていますは、PostgreSQL - 構文

「BY GROUP」予想外の結果が「DISTINCT ON」との私の不適切な使用に行うことができます戻ったことに気づきましたこれを真っ直ぐにしてください。実際のクエリは非常に複雑ですので、私よダムそれダウン:

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 
\. 

私は明確な選択をしようとしている:

私はOBJECT_IDとタイムスタンプで構成され、テーブル/インナークエリを持っていますID、(それが思わ)私は、これは私が必要なものないと思うので、結果は

[5、4、1、3、2]である必要があり、逆CHRONにタイムスタンプで重複排除/

を命じた:

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

テスト/監査の目的で、タイムスタンプフィールドを含めることがあります。私はそのクエリに別のフィールドを含める方法を見つけることができないようです。

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

答えて

14

にできるようにするにはすべての列を選択していないだけobject_idMAX(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 ; 
使用することができます

あなたがobject_idによってevent_timestamp DESCとしないことにより、注文した結果をしたい場合は、派生テーブルまたは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 ; 
OVER

または集約MAX()

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 ; 
+0

ありがとう!あなたの2番目の例は、私が理解しようとしていた構文でした。後でパフォーマンスのために他のクエリをテストし、それらを使用できるかどうかを確認します。私はユーザーの入力に基づいてこのクエリを生成しています。その2番目の例は「簡単に実行可能です」です。 –

3

それはおそらくこれに対処する最善の方法はありませんが、あなたは窓関数を使用して試すことができます:

SELECT DISTINCT object_id, MAX(event_timestamp) 
OVER (PARTITION BY object_id) 
FROM test_select ORDER BY max DESC; 

一方から、それは同様に動作します

SELECT object_id, MAX(event_timestamp) as max_event_timestamp 
FROM test_select 
GROUP BY object_id 
ORDER BY max_event_timestamp DESC;