2013-09-22 19 views
11

"GROUP BY" "DISTINCT AÇIK" ve bir veritabanı sorgusu Birini umuyorumPostgreSQL - sözdizimi

"ardından GROUP" beklenmedik sonuçlar "DISTINCT ON" ve benim yanlış kullanım için yapabileceğiniz dönüyordu fark Beni bunun üzerine koy. gerçek sorgu oldukça karmaşıktır, bu yüzden olacak dilsiz aşağı:

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

ben ayrı seçmek çalışıyorum:

Bir object_id ve bir zaman damgası oluşan bir tablo/iç sorgu var kimlik,/

böylece sonuç olmalıdır ters Chron üzerinde zaman damgası ile tekilleştirilmez sipariş [4, 1, 3, 2, 5]

Bu neye ihtiyacım yok bence (o görünüyor):

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

Test/denetim amacıyla, bazen zaman damgası alanını dahil etmek istiyorum. Bu sorgu ile başka bir alanın nasıl ekleneceğini anlayamıyorum.

Yukarıda benim sql'mda göze çarpan sorunlara veya denetim bilgilerini nasıl ekleyeceğinize dair önerilere işaret eden var mı?

cevap

14

edebilmek tüm sütunları seçmek ve sadece object_id ve MAX(event_timestamp), sen DISTINCT ON

SELECT DISTINCT ON (object_id) 
    object_id, event_timestamp ---, more columns 
FROM test_select 
ORDER BY object_id, event_timestamp DESC ; 
kullanabilirsiniz , Sen ROW_NUMBER() gibi, pencere işlevleri kullanabilirsiniz Alternatif

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 ; 

: Eğer event_timestamp DESC tarafından değil, object_id tarafından sipariş sonuçlarını istiyorsanız

, bir türetilmiş tablo veya bir CTE eklemenize gerek

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 ile

veya toplam 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

teşekkürler! İkinci örneğiniz anlamaya çalıştığım sözdizimiydi. Daha sonra performans için diğer sorguları test edip bunları kullanıp kullanamayacağımı göreceğim. Bu sorguyu, kullanıcı girdisine dayanarak üretken olarak yapıyorum ve bu ikinci örnek "kolayca yapılabilir". –

3

Muhtemelen bu başa çıkmanın en iyi yolu değildir ama pencere işlevini kullanarak deneyebilirsiniz: o kadar iyi çalışır Öte itibaren

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;