PostgreSQL:计算一行中包含值的列数
Posted
技术标签:
【中文标题】PostgreSQL:计算一行中包含值的列数【英文标题】:PostgreSQL: Count number of columns in a row that contain a value 【发布时间】:2018-05-02 20:43:00 【问题描述】:假设我有一个包含以下列的表格:
身份证
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 列):
case col1 when 0 then 1 else 0 end + case col col1 when 0 then 1 else 0 end...
【问题讨论】:
【参考方案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;
Demolad2925 (c)
More about JSON functions.
【讨论】:
我真的很喜欢这种方法 :) Demo【参考方案2】:你可以使用某种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
【讨论】:
【参考方案3】:如果您事先知道列名,您可以构建一个数组、取消嵌套和聚合以获取行中零的计数。 示例:
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
【讨论】:
以上是关于PostgreSQL:计算一行中包含值的列数的主要内容,如果未能解决你的问题,请参考以下文章