PostgreSQL - “DISTINCT ON” and “GROUP BY” syntax

前端 未结 2 762
悲&欢浪女
悲&欢浪女 2021-02-05 12:07

I realized that a database query was returning unexpected results do to my improper use of \"DISTINCT ON\" and \"GROUP BY\"

I\'m hoping someone can set me straight on th

相关标签:
2条回答
  • 2021-02-05 12:26

    To be able to select all columns and not only object_id and MAX(event_timestamp), you can use DISTINCT ON

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

    If you want the results ordered by event_timestamp DESC and not by object_id, you need to include it in a derived table or a 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 ;
    

    Alternatively, you can use window functions, like 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 ;
    

    or aggregate MAX() with 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 ;
    
    0 讨论(0)
  • 2021-02-05 12:35

    It is probably not the best way of dealing with this but you can try using window function:

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

    From the other hand it works as well:

    SELECT object_id, MAX(event_timestamp) as max_event_timestamp
    FROM test_select 
    GROUP BY object_id 
    ORDER BY max_event_timestamp DESC;
    
    0 讨论(0)
提交回复
热议问题