lur*_*urv 2 postgresql array unpivot
我有诸如role1
、role2
、role3
等列。它们都是布尔值。
我想在此表上创建一个视图,该视图具有类型为 的角色列text[]
。如果有列TRUE, FALSE, TRUE
,则视图将包含["role1", "role3"]
.
有什么好的方法可以做到这一点,并且不会爆炸成大量的CASE WHEN
\xc2\xb4s 吗?澄清一下,我可以使用 O(n) CASE WHEN
,但不能使用 O(2^n) ,这是目前似乎需要的。:)
我建议VALUES
在横向子查询中使用表达式。
SELECT t.id, a.roles
FROM tbl t
CROSS JOIN LATERAL (
SELECT ARRAY(
SELECT col
FROM (
VALUES
('role1', role1) -- eligible columns
, ('role2', role2)
, ('role3', role3)
) x(col, val)
WHERE val
)
) a(roles);
Run Code Online (Sandbox Code Playgroud)
这将列“逆透视”为行,因此我们可以处理一组而不是一行。
正如a_horse 所演示的,json
( b
) 具有足够的通用性,足以涵盖此任务。boolean
在处理所有列时,您无需拼写出符合条件的列。但无论如何,您似乎都必须拼出符合条件的列。
细微的差别:对于“无限定值”( {}
),这会返回一个空数组,而 a_horse 的查询也会返回NULL
相同的值。
由于以下三个原因,这应该要快得多:
array_agg()
. 看:
或者,更简单:CASE
用 . 连接的普通表达式concat_ws()
。如果字符串足够好:
SELECT t.id
, concat_ws(','
, CASE WHEN role1 THEN 'role1' END -- eligible columns
, CASE WHEN role2 THEN 'role2' END
, CASE WHEN role3 THEN 'role3' END) AS roles_string
FROM tbl t;
Run Code Online (Sandbox Code Playgroud)
应该是最快的解决方案。而且没有那么冗长。看:
或者获取与上面相同的数组:
SELECT t.id
, string_to_array(
concat_ws(
','
, CASE WHEN role1 THEN 'role1' END -- eligible columns
, CASE WHEN role2 THEN 'role2' END
, CASE WHEN role3 THEN 'role3' END)
, ',') AS roles
FROM tbl t;
Run Code Online (Sandbox Code Playgroud)
我们还可以从系统目录动态生成符合条件的列的列表。(如果您根本不想拼出列。)
或者缩小到json
( b
) 技术的合格列,以尽早消除可能昂贵的噪音。看:
db<>在这里摆弄- 包括。以上所有内容、a_horse 的 jsonb 查询以及一些变体