假设我有一个包含以下列的表:
编号
Col1中
col2的
COL3
COL4
。
*请注意,我有50个这样的列('col1'...'col50')
对于每一行,我想计算以'col'开头的列数(所以col1,col2等),它们还包含一个特定的整数值(例如0)。
所以如果我的数据是:
Id, Col1, Col2, Col3, Col4
0, 0, 1, 2, 1
1, 1, 2, 0, 1
2, 1, 0, 5, 0
3, 0, 0, 0, 4
我的结果将是:
Id, Count
0, 1
2, 1
2, 2
3, 3
显然这需要扩展到50列,所以我不想硬编码列名(我需要动态/循环)。我也将用我正在寻找的其他值重复这个,问题的内容可以简化为上述结果。
我不知道如何做到这一点。我想到了一个函数,它接受一个列名,一个查找值和一个计数器,然后返回一个总计和当前计数器位置或其他东西。我必须做一个WHILE循环来调用函数,直到到达终点计数器。
目标是更换有效的东西,但眼睛疼痛且无法重复使用(有50列):
案例col1 0时1然后0结束+案件col col1 0时1然后0结束...
答案 0 :(得分:1)
with t(id, col1, col2, col3, col4) as (values
(0,0,1,2,1),
(3,0,0,0,4))
select * from t cross join lateral (
select count(*) as cnt
from json_each_text(to_json(t))
where key like 'col%' and value = '0') as j;
Demo(c)
答案 1 :(得分:0)
您可以使用某种PIVOT
:
SELECT Id, cnt
FROM tab
JOIN LATERAL ( SELECT COUNT(*) AS cnt_0
FROM (VALUES(col1),(col2),(col3),(col4)) s(c)
WHERE s.c=0) AS sub ON true
ORDER BY id;
<强> DBFiddle Demo 强>
答案 2 :(得分:0)
如果您事先知道列名,则可以构建一个数组,不需要并聚合以获取行中的零数。 例如:
WITH t (Id, Col1, Col2, Col3, Col4) AS (
VALUES
(0, 0, 1, 2, 1),
(1, 1, 2, 0, 1),
(2, 1, 0, 5, 0),
(3, 0, 0, 0, 4)
)
, unnested AS (
SELECT id, (UNNEST(ARRAY[Col1, Col2, Col3, Col4]) = 0)::INT is_zero
FROM t
)
SELECT id, SUM(is_zero) zeros
FROM unnested
GROUP BY 1
否则,使用json函数重塑表,过滤列名(键)和值并聚合。
WITH t (Id, Col1, Col2, Col3, Col4) AS (
VALUES
(0, 0, 1, 2, 1),
(1, 1, 2, 0, 1),
(2, 1, 0, 5, 0),
(3, 0, 0, 0, 4)
)
SELECT id, COUNT(*)
FROM t, JSON_EACH(ROW_TO_JSON(t)) kv
WHERE kv.key ~ 'col\d+'
AND (kv.value::TEXT)::INT = 0
GROUP BY 1