PostgreSQL:计算一行中包含值的列数

时间:2018-05-02 20:43:01

标签: postgresql

假设我有一个包含以下列的表:

编号

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结束...

3 个答案:

答案 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)

lad2925

More about JSON functions.

答案 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