Postgresql
組中最後一個值的通用視圖
我正在嘗試創建一個視圖來顯示組中的最後一個值。尋找更通用的查詢。
CREATE TABLE a ( id INTEGER, seq INTEGER, val VARCHAR2(16), PRIMARY KEY(id,seq) ); -- View 1 CREATE VIEW v1 AS SELECT a.* FROM a, (SELECT id, MAX(seq) from a GROUP BY id) b WHERE a.id=b.id AND a.seq=b.seq -- View 2 CREATE VIEW v2 AS SELECT a.* FROM a WHERE a.seq=(SELECT seq from a b WHERE a.id=b.id ORDER BY seq DESC LIMIT 1)
當我想列出所有記錄時,視圖 1 表現更好。
當我這樣做時,View 2 表現更好
SELECT * FROM v2 WHERE id=?
因為這個觀點是提供給局外人的,所以我希望它盡可能通用。有沒有辦法告訴 PostgreSQL 這兩個查詢是等價的並讓它自動選擇它們?
這種形式
DISTINCT ON
通常比v1
or快v2
:CREATE VIEW v3 AS SELECT DISTINCT ON (id) a.* FROM a ORDER BY id, seq DESC NULLS LAST;
你會
id
在它上面得到排序的輸出(按),這通常是一個受歡迎的副作用。細微差別:這種形式包括一行 id 中只有 NULL 值的
seq
. 通常,這也將是一個受歡迎的效果。seq
與if無關NOT NULL
。如果性能很重要,我強烈建議創建一個匹配的(!)形式的多列索引:
CREATE INDEX a_id_seq_idx ON a (id, seq DESC NULLS LAST);
在這個相關問題下有更多細節和更多替代方案:
根據輸入切換查詢
相反,如果您對切換技術本身感興趣,則可以創建一個表函式,而不是使用 id 作為參數的視圖。
CREATE OR REPLACE FUNCTION f_a(_id int DEFAULT NULL) RETURNS SETOF a AS $func$ BEGIN IF _id IS NULL THEN RETURN QUERY SELECT ... ; ELSE RETURN QUERY SELECT ... WHERE id = _id; END IF; END $func$ LANGUAGE plpgsql;
稱呼:
SELECT * FROM f_a(); -- for the whole table SELECT * FROM f_a(123); -- for a particular id
可以通過更多參數進行改進。
這種方法非常適合簡單的呼叫。甚至可以節省一些計劃成本,並且通常比原始 SQL 更快。但請注意,plpgsql 函式會構成優化障礙。函式的主體不能在更大查詢的上下文中內聯或優化(例如視圖或簡單的 SQL 函式)。更多相關答案: