使用 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 语句计算非空列的数量的主要内容,如果未能解决你的问题,请参考以下文章

如何根据另一列的值创建空列或非空列?

Scala DataFrame,将非空列的值复制到新列中

Pyspark:如何将现有非空列的元组列表作为数据框中的列值之一返回

如何将一个表与另一个表连接,然后计算非空列并将它们按另外两个字段分组?

oracle如何向空表中添加一个类型为clob的非空列

ALTER TABLE,在非空列中设置空,PostgreSQL 9.1