【问题标题】:Count the number of not null columns using a case statement使用 case 语句计算非空列的数量
【发布时间】: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
  • 我很确定我需要使用计数器(循环?),但在 stackoverflow 或在线上找不到任何解决此问题的内容...

标签: sql sql-server


【解决方案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
        

        【讨论】:

          猜你喜欢
          • 2018-01-29
          • 2022-06-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-18
          • 2012-12-22
          • 2017-07-26
          • 1970-01-01
          相关资源
          最近更新 更多