Postgresql
從沒有 NULL 元素的多列創建數組
我正在嘗試建構一個查詢以將舊表中的多個列聚合在一起,該舊表以類似的結構儲存,如下所示:
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"]