Postgresql
SELECT DISTINCT ON,按另一列排序
請考慮下表
test
:CREATE TABLE test(col1 int, col2 varchar, col3 date); INSERT INTO test VALUES (1,'abc','2015-09-10') , (1,'abc','2015-09-11') , (2,'xyz','2015-09-12') , (2,'xyz','2015-09-13') , (3,'tcs','2015-01-15') , (3,'tcs','2015-01-18');
postgres=# select * from test; col1 | col2 | col3 ------+------+------------ 1 | abc | 2015-09-10 1 | abc | 2015-09-11 2 | xyz | 2015-09-12 2 | xyz | 2015-09-13 3 | tcs | 2015-01-15 3 | tcs | 2015-01-18
我想要一個按日期順序排列的返回集:
col1 | col2 | col3 ------+------+------------ 2 | xyz | 2015-09-13 1 | abc | 2015-09-11 3 | tcs | 2015-01-18
我設法完成的工作
distinct on
:select distinct on (col1) col1, col2, col3 from test order by col1, col3 desc; col1 | col2 | col3 ------+------+------------ 1 | abc | 2015-09-11 2 | xyz | 2015-09-13 3 | tcs | 2015-01-18
而不是我需要的
having
:select distinct on (col1) col1, col2, col3 from test group by col1, col2, col3 having col3 = max(col3) col1 | col2 | col3 ------+------+------------ 1 | abc | 2015-09-10 2 | xyz | 2015-09-13 3 | tcs | 2015-01-18
您仍然可以使用
DISTINCT ON
. 只需將其包裝到外部查詢中即可根據您的需要進行排序。看:SELECT * FROM ( SELECT DISTINCT ON (col1) col1, col2, col3 FROM test ORDER BY col1, col3 DESC ) sub ORDER BY col3 DESC, col2;
假設在
col2
功能上取決於col1
,所以我們可以在內部查詢DISTINCT ON
中忽略它。ORDER BY
但我將它添加到外部ORDER BY
作為有意義的決勝局。如果col2
沒有 不是唯一的col1
,您可能會col1
另外附加。假設
col3
被定義NOT NULL
。其他附加NULLS LAST
:每行只有幾
(col1)
行,這通常是最快的解決方案。看:db<>在這裡擺弄
帶有視窗函式的子查詢
row_number()
(如 Vérace 建議的)是一種有效的替代方法,但通常速度較慢。我做了很多測試,但你自己試試。它必須排序兩次,就像DISTINCT ON
(如果預期會更快,它可能會在內部切換到散列算法),但它保留內部查詢之後的所有行,增加了不必要的成本。無論哪種方式,您都不需要ORDER BY
內部查詢:SELECT col1, col2, col3 FROM ( SELECT col1, col2, col3 , row_number() OVER (PARTITION BY col1 ORDER BY col3 DESC) AS rn FROM test ) sub WHERE rn = 1 ORDER BY col3 DESC, col2;
如果不需要,請不要使用 CTE。它通常要貴得多(直到 Postgres 12,主要是修復了這個問題)。
對於每行很多
col1
,索引變得更加重要,並且通常有更快的替代方案。看:此外,與 Oracle 或 SQL Server 不同,PostgreSQL 不使用術語“分析函式”來表示視窗函式。(關於這些功能的“分析”是什麼?)