選擇指定數量的唯一 ID,其中第二列是唯一的
查看下面的範例,從第一行 (
id=9
) 開始,然後繼續向下,選擇我們尚未看到的具有 ‘s的行的**限制。**我們“選擇”是因為我們還沒有. 我們繼續像這樣向下工作,但是當我們到達時,我們跳過它,因為我們已經有了(從帶有 的行開始)。我們以同樣的方式繼續,我們最終停下來,因為我們已經積累了行(我們想要的限制)。4``sec``id=9``sec=1``id=7``sec=5``id=8``id=3``4
id | sec ----+----- 9 | 1 <- 1 8 | 5 <- 2 7 | 5 # skip, already have sec=5 6 | 4 <- 3 5 | 1 # skip, already have sec=1 4 | 1 # skip, already have sec=1 3 | 3 <- 4 2 | 2 1 | 1
當然,
SQL
算法可以(將!)與我描述的不同。期望的結果:
id ---- 9 8 6 3 (4 rows)
如果我想增加對
5
行的限制,那麼帶有的id=2
行將包含在結果中。但是,如果我增加對行的限制,則不會添加6
帶有的行,因為已經看到了。id=1``sec=1
注意:雖然沒關係,但我在PostgreSQL 9.3.1上。
如果您想快速建構表格以進行測試:
CREATE TABLE my_table (id serial primary key, sec integer DEFAULT 0 NOT NULL); INSERT INTO my_table (sec) VALUES (1) , (2) , (3) , (1) , (1) , (4) , (5) , (5) , (1); CREATE INDEX index_my_table_on_sec ON my_table (sec);
在 Postgres 中,這更簡單
DISTINCT ON
:SELECT * FROM ( SELECT DISTINCT ON (sec) id, sec FROM tbl ORDER BY sec, id DESC ) sub ORDER BY id DESC LIMIT 4;
在這個相關答案中的詳細解釋:
對於大桌子和**小
LIMIT
**桌子,這個和@a_horse 的解決方案都不是很有效。子查詢會遍歷整個表,浪費很多時間……遞歸 CTE
過去,我曾嘗試過使用遞歸 CTE 解決類似問題,但未能解決,於是我求助於 PL/pgSQL 的程序解決方案。例子:
最後,這是一個有效的 rCTE:
WITH RECURSIVE cte AS ( ( -- parentheses required SELECT id, '{}'::int[] AS last_arr, ARRAY[sec] AS arr FROM tbl ORDER BY id DESC LIMIT 1 ) UNION ALL ( SELECT b.id, c.arr , CASE WHEN b.sec = ANY (c.arr) THEN c.arr ELSE b.sec || c.arr END FROM cte c JOIN tbl b ON b.id < c.id WHERE array_length(c.arr, 1) < 4 ORDER BY id DESC LIMIT 1 ) ) SELECT id, arr[1] AS sec FROM cte WHERE last_arr <> arr;
它沒有我希望的那麼快或優雅,也沒有下面的函式快,但在我的測試中比上面的查詢快。
PL/pgSQL 函式
目前最快:
CREATE OR REPLACE FUNCTION f_first_uniq(_rows int) RETURNS TABLE (id int, sec int) AS $func$ DECLARE _arr int[]; BEGIN FOR id, sec IN SELECT t.id, t.sec FROM tbl t ORDER BY t.id DESC LOOP IF sec = ANY (_arr) THEN -- do nothing ELSE RETURN NEXT; _arr := _arr || sec; EXIT WHEN array_length(_arr, 1) >= _rows; END IF; END LOOP; END $func$ LANGUAGE plpgsql;
稱呼:
SELECT * FROM f_first_uniq(4);
**SQL Fiddle**展示了這三個。
可以適用於任何以表名和列名作為參數的表和動態 SQL
EXECUTE
…何必?
在只有
30k
行的測試表中,該函式的執行速度比上述查詢快 2000 倍(已經比 a_horse 的版本快 30%)**。**這種差異隨著表的大小而增加。該函式的性能幾乎是恆定的,而查詢的性能逐漸變差,因為它首先嘗試在所有表中找到不同的值。在具有一百萬行的表中嘗試此操作…