2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3

F.18. intagg — 整數聚合器和列舉器 #

intagg 模組提供了一個整數聚合器和一個列舉器。intagg 現在已經過時,因為內建函式提供了其功能的超集。但是,該模組仍然作為對內建函式的相容性包裝器提供。

F.18.1. 函式 #

聚合器是一個聚合函式 int_array_aggregate(integer),它生成一個包含其接收的整數的整數陣列。這是 array_agg 的一個包裝器,它對任何陣列型別執行相同的操作。

列舉器是一個函式 int_array_enum(integer[]),它返回 setof integer。它本質上是聚合器的逆操作:給定一個整數陣列,將其展開為一組行。這是 unnest 的一個包裝器,它對任何陣列型別執行相同的操作。

F.18.2. 示例用法 #

許多資料庫系統都有多對多表的概念。這樣的表通常位於兩個索引表之間,例如

CREATE TABLE left_table  (id INT PRIMARY KEY, ...);
CREATE TABLE right_table (id INT PRIMARY KEY, ...);
CREATE TABLE many_to_many(id_left  INT REFERENCES left_table,
                          id_right INT REFERENCES right_table);

通常用法如下:

SELECT right_table.*
FROM right_table JOIN many_to_many ON (right_table.id = many_to_many.id_right)
WHERE many_to_many.id_left = item;

這將返回左側表中某個條目在右側表中的所有條目。這是 SQL 中一個非常常見的構造。

現在,對於 many_to_many 表中非常多的條目,這種方法可能會很麻煩。通常,這樣的連線會為左側表中特定條目的每個右側條目導致索引掃描和獲取。如果您有一個非常動態的系統,您也無能為力。但是,如果您的資料相當靜態,您可以建立一個帶有聚合器的摘要表。

CREATE TABLE summary AS
  SELECT id_left, int_array_aggregate(id_right) AS rights
  FROM many_to_many
  GROUP BY id_left;

這將建立一個表,其中左側項有一行,右側項有一個數組。現在,如果沒有辦法使用該陣列,這將是無用的;這就是為什麼有一個數組列舉器。您可以這樣做:

SELECT id_left, int_array_enum(rights) FROM summary WHERE id_left = item;

上面使用 int_array_enum 的查詢會產生與以下查詢相同的結果:

SELECT id_left, id_right FROM many_to_many WHERE id_left = item;

區別在於,對摘要表的查詢只需要從表中獲取一行,而直接對 many_to_many 的查詢必須為每個條目進行索引掃描和行獲取。

在一個系統中,EXPLAIN 顯示一個成本為 8488 的查詢被降低到成本 329。原始查詢是涉及 many_to_many 表的連線,該連線被替換為:

SELECT id_right, count(id_right) FROM
  ( SELECT id_left, int_array_enum(rights) AS id_right
    FROM summary
    JOIN (SELECT id FROM left_table
          WHERE id = item) AS lefts
    ON (summary.id_left = lefts.id)
  ) AS list
  GROUP BY id_right
  ORDER BY count DESC;

提交更正

如果您在文件中看到任何不正確、與您對特定功能的經驗不符或需要進一步澄清的內容,請使用 此表格 報告文件問題。