Postgresql

組中最後一個值的通用視圖

  • January 14, 2014

我正在嘗試創建一個視圖來顯示組中的最後一個值。尋找更通用的查詢。

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通常比v1or快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);

在這個相關問題下有更多細節和更多替代方案:

在每個 GROUP BY 組中選擇第一行?

根據輸入切換查詢

相反,如果您對切換技術本身感興趣,則可以創建一個表函式,而不是使用 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 函式)。更多相關答案:

PostgreSQL 儲存過程性能

引用自:https://dba.stackexchange.com/questions/56721