使用 case 语句计算非空列的数量
Posted
技术标签:
【中文标题】使用 case 语句计算非空列的数量【英文标题】:Count the number of not null columns using a case statement 【发布时间】:2018-01-25 02:01:15 【问题描述】:我的查询需要一些帮助...我正在尝试计算每个房子的名字,所有 col# 都是名字。
查询:
SELECT House#,
COUNT(CASE WHEN col#1 IS NOT NULL THEN 1 ELSE 0 END) +
COUNT(CASE WHEN col#2 IS NOT NULL THEN 1 ELSE 0 END) +
COUNT(CASE WHEN col#3 IS NOT NULL THEN 1 ELSE 0 END) as count
FROM myDB
WHERE House# in (house#1,house#2,house#3)
GROUP BY House#
期望的结果:
房子 1 - 计数是 3 / 房子 2 - 计数是 2 / 房子 3 - 计数是 1
...根据我当前的查询,count 的结果将只有 3 个
【问题讨论】:
它们总是用逗号分隔吗? 如果您能够更改数据库架构,我建议您改为这样做。列中的逗号分隔值不是一个好主意。理想情况下,您应该有一个HouseName
表,每行只有一个房子/名称组合。然后你的查询就变成了一个简单的计数/组。
你有没有名字,姓氏或任何其他逗号的可能性?
对不起,我有点(非常)模糊......逗号只是分隔名称。如果我把它写在一个问答段落中,那就是……彼得、保罗和玛丽住在 1 号房子里。莎拉和莎莉住在 2 号房子里。乔住在 3 号房子里。人们怎么可能住在 1 号房子里和房子 2 和房子 3....回答,恭敬地是 3,2,1
我很确定我需要使用计数器(循环?),但在 *** 或在线上找不到任何解决此问题的内容...
【参考方案1】:
在这种情况下,计数名称似乎与计数逗号 (,
) 加一相同:
SELECT House_Name,
LEN(Names) - LEN(REPLACE(Names,',','')) + 1 as Names
FROM dbo.YourTable;
【讨论】:
@scsimon 是的,对不起,我通常会等待澄清,但出于某种原因,我认为在这种情况下很清楚......我的错【参考方案2】:自从Lamak 抢了我的风头后,另一个选择是拆分它并规范化您的数据,然后聚合。这使用 common split function,但您可以使用任何东西,包括用于 SQL Server 2016+ 或您自己的 STRING_SPLIT...
declare @table table (house varchar(16), names varchar(256))
insert into @table
values
('house 1','peter, paul, mary'),
('house 2','sarah, sally'),
('house 3','joe')
select
t.house
,NumberOfNames = count(s.Item)
from
@table t
cross apply dbo.DelimitedSplit8K(names,',') s
group by
t.house
【讨论】:
好一个。尽管阅读了操作员的最后一条评论,但我们都错了 哈哈,我们是根据@Lamak 的评论来判断的 是的,我不认为这样的事情可以在 sql 中以 100% 的精度完成【参考方案3】:注意到你得到的答案对于他们正在做的事情来说是多么复杂?那是因为关系数据库并非旨在以这种方式存储数据。
另一方面,如果您将数据结构更改为以下内容:
house name
1 peter
1 paul
1 mary
2 sarah
2 sally
3 joe
现在的查询是:
select house, count(name)
from housenames
group by house
所以我的建议是这样做:使用更适合 SQL Server 使用的设计,并且您的查询变得更简单、更高效。
【讨论】:
【参考方案4】:一个肮脏的技巧是用空字符串替换逗号并比较长度:
SELECT house +
' has ' +
CAST((LEN(names) - LEN(REPLACE(names, ',', '')) + 1) AS VARCHAR) +
' names'
FROM mytable
【讨论】:
【参考方案5】:您可以使用xml解析并找到如下计数:
Select *, a.xm.value('count(/x)','int') from (
Select *, xm = CAST('<x>' + REPLACE((SELECT REPLACE(names,', ','$$$SSText$$$') AS [*] FOR XML PATH('')),'$$$SSText$$$','</x><x>')+ '</x>' AS XML) from #housedata
) a
【讨论】:
【参考方案6】:select House, 'has '+cast((LEN(Names)-LEN(REPLACE(Names, ',', ''))+1) as varchar)+' names'
from TempTable
【讨论】:
以上是关于使用 case 语句计算非空列的数量的主要内容,如果未能解决你的问题,请参考以下文章
Pyspark:如何将现有非空列的元组列表作为数据框中的列值之一返回