Postgresql

從沒有 NULL 元素的多列創建數組

  • January 17, 2017

我正在嘗試建構一個查詢以將舊表中的多個列聚合在一起,該舊表以類似的結構儲存,如下所示:

CREATE TEMPORARY TABLE foo AS
SELECT * FROM ( VALUES
 (1,'Router','Networking','Sale',NULL),
 (2,NULL,'Router','Networking','Sale'),
 (3,NULL,NULL,'Networking','Sale'),
 (4,NULL,NULL,NULL,NULL)
) AS t(id,tag_1,tag_2,tag_3,tag_4);

不是我想要的一個例子

這是我要建構的查詢範例:

SELECT ID, json_build_array(Tag_1, Tag_2, Tag_3, Tag_4) AS tags
FROM table

問題是上述查詢將行中的 NULL 值添加到數組中:

ID  Tags
--------------------------------------------------
1   ['Router', 'Networking', 'Sale', null]
2   [null, 'Router', 'Networking', 'Sale']
3   [null, null, 'Networking', 'Sale']
4   [null, null, null, null]

我想避免編寫過於復雜的CASE WHEN語句來過濾掉 NULL,而且我對使用 PostgreSQL 的 JSON 數據類型還是很陌生。在 Postgres 中建構 JSON 數組時,我是否可以避免包含 NULL?

我建議不要使用 JSON 數組,而是使用本機 SQL 數組語法,這種語法可能更快、更有效地儲存。它的類型也更強。根據文件,JSON 數組是*“可能是異構類型的” 。*

我也不會經常這樣做。我會更改表的架構以ARRAY在表本身上有一個(最好是 SQL)來儲存標籤,而不會在列中儲存 null。這可以讓您走上更正架構的道路。

建構數組

嚴格類型的 PostgreSQL 數組

只需使用 ARRAY 文字建構子。

SELECT id, ARRAY[tag_1,tag_2,tag_3,tag_4] FROM foo;
id |             array             
----+-------------------------------
 1 | {Router,Networking,Sale,NULL}
 2 | {NULL,Router,Networking,Sale}
 3 | {NULL,NULL,Networking,Sale}
 4 | {NULL,NULL,NULL,NULL}

一個 JSON 數組

SELECT id, json_build_array(tag_1,tag_2,tag_3,tag_4) FROM foo;
id |            json_build_array            
----+----------------------------------------
 1 | ["Router", "Networking", "Sale", null]
 2 | [null, "Router", "Networking", "Sale"]
 3 | [null, null, "Networking", "Sale"]
 4 | [null, null, null, null]
(4 rows)

無需手動過濾空值coalesce

嚴格類型的 PostgreSQL 數組

您可以通過將上述內容包裝在array_remove.

SELECT id, array_remove(ARRAY[tag_1,tag_2,tag_3,tag_4], null)
FROM foo;

id |       array_remove       
----+--------------------------
 1 | {Router,Networking,Sale}
 2 | {Router,Networking,Sale}
 3 | {Networking,Sale}
 4 | {}

JSON 數組

SELECT id,jsonb_agg(elem)
FROM (SELECT id, ARRAY[tag_1,tag_2,tag_3,tag_4] FROM foo) AS g
CROSS JOIN LATERAL unnest(g.array)
 WITH ORDINALITY AS t(elem,ord)
WHERE elem IS NOT NULL
GROUP BY id
ORDER BY id;

id |            jsonb_agg             
----+----------------------------------
 1 | ["Router", "Networking", "Sale"]
 2 | ["Router", "Networking", "Sale"]
 3 | ["Networking", "Sale"]

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