Sat*_*iel 9 postgresql array json postgresql-9.4
我正在尝试构建一个查询以将旧表中的多个列聚合在一起,该表存储在类似的结构中,如下所示:
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);
Run Code Online (Sandbox Code Playgroud)
这是我要构建的查询的示例:
SELECT ID, json_build_array(Tag_1, Tag_2, Tag_3, Tag_4) AS tags
FROM table
Run Code Online (Sandbox Code Playgroud)
问题是上面的查询将行中的 NULL 值添加到数组中:
ID Tags
--------------------------------------------------
1 ['Router', 'Networking', 'Sale', null]
2 [null, 'Router', 'Networking', 'Sale']
3 [null, null, 'Networking', 'Sale']
4 [null, null, null, null]
Run Code Online (Sandbox Code Playgroud)
我想避免编写过于复杂的CASE WHEN语句来过滤掉 NULL,而且我对使用 PostgreSQL 的 JSON 数据类型还是个新手。在 Postgres 中构建 JSON 数组时,是否可以避免包含 NULL?
Eva*_*oll 12
我建议不要使用 JSON 数组,而是使用本机 SQL 数组语法,这可能会更快、更有效地存储。它也是更强的类型。根据文档,JSON 数组是“可能的异构类型”。
我也不会经常这样做。我会改变表的模式,ARRAY在表本身上有一个(最好是 SQL)来存储标签,而不会在列中存储空值。这可以让您走上更正模式的道路。
只需使用 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}
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
coalesce您可以通过将上述内容包装在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 | {}
Run Code Online (Sandbox Code Playgroud)
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"]
Run Code Online (Sandbox Code Playgroud)