【问题标题】:Counting if data exists in a row计算数据是否连续存在
【发布时间】:2013-11-14 03:27:12
【问题描述】:

大家好,我有以下要查询的示例数据。

MemberID            AGEQ1       AGEQ2       AGEQ2 
-----------------------------------------------------------------
1217                2           null        null        
58458               3           2           null            
58459               null        null        null            
58457               null        5           null            
299576              6           5           7

我需要做的是查找表格,如果任何 AGEx COLUMN 包含任何数据,那么它会计算每列中该行有数据的次数

结果示例:

对于 memberID 1217,计数为 1

对于 memberID 58458,计数为 2

对于 memberID 58459,计数将为 0 或 null

对于 memberID 58457,计数为 1

对于 memberID 299576,计数为 3

如果我查询整个表,这就是它在 SQL 中的样子

1 个孩子 - 2 个

2 个孩子 - 1 个

3 个孩子 - 1 个

0 个孩子 - 1 个

到目前为止,我一直在使用以下查询进行此操作,该查询效率不高,并且确实给出了不正确的计数,因为人们可以回答 AGE 问题的多种组合。此外,我必须编写多个查询并将 is null 更改为 not null,具体取决于我要计算一个人有多少孩子

select COUNT (*) as '1 Children' from Member
where AGEQ1 is not null
and AGEQ2 is null
and AGEQ3 is null

上面的查询只给了我 1 的答案,但我也希望能够计算其他列的数据

希望这是好的和清晰的,提前谢谢你

【问题讨论】:

  • 您有多少个AGEx 列?是固定的吗?而这怎么可能同时是mysql和sql server?
  • 对不起已经改变了,我有 6 个,但我只展示了 3 个作为示例,但原理相同,我不想为每个组合进行多个查询

标签: sql sql-server sql-server-2008


【解决方案1】:

如果所有列都是整数,您可以利用整数数学 - 将列除以自身将产生 1,除非值为 NULL,在这种情况下,COALESCE 可以将结果 NULL 转换为 0。

SELECT 
    MemberID,
    COALESCE(AGEQ1 / AGEQ1, 0)
  + COALESCE(AGEQ2 / AGEQ2, 0)
  + COALESCE(AGEQ3 / AGEQ3, 0)
  + COALESCE(AGEQ4 / AGEQ4, 0)
  + COALESCE(AGEQ5 / AGEQ5, 0)
  + COALESCE(AGEQ6 / AGEQ6, 0)
FROM dbo.table_name; 

要获得每个孩子的人数,然后:

;WITH y(y) AS 
(
  SELECT TOP (7) rn = ROW_NUMBER() OVER 
    (ORDER BY [object_id]) - 1 FROM sys.objects
),
x AS
( 
  SELECT 
     MemberID,
     x = COALESCE(AGEQ1 / AGEQ1, 0)
       + COALESCE(AGEQ2 / AGEQ2, 0)
       + COALESCE(AGEQ3 / AGEQ3, 0)
       + COALESCE(AGEQ4 / AGEQ4, 0)
       + COALESCE(AGEQ5 / AGEQ5, 0)
       + COALESCE(AGEQ6 / AGEQ6, 0)
  FROM dbo.table_name
)
SELECT 
  NumberOfChildren = y.y, 
  NumberOfPeopleWithThatMany = COUNT(x.x) 
FROM y LEFT OUTER JOIN x ON y.y = x.x
GROUP BY y.y ORDER BY y.y; 

【讨论】:

  • 天哪,这很棘手......如果您希望未来的开发人员了解正在发生的事情,我会坚持使用另一个答案中的案例陈述:)
  • 太好了,这也让我得到了与其他答案相似的结果,但是我如何才能得到一个有 1 个孩子或 2 个孩子等的人的总数?
  • 哦,哇,你用那个完全击中了头,即使我不完全理解最后一个答案:) 非常感谢!接受!!
【解决方案2】:

我会考虑使用UNPIVOT。这将使您的宽列变成行。由于您不关心列中的值,只关心值的存在/不存在,这将为每个非空列生成一行。

然后,技巧就变成了将其混合成所需的输出格式。它可能做得更干净,但我喜欢“展示我的作品”,以便其他人可以根据他们的需求进行调整。

SQLFiddle

-- Using the above logic
WITH HadAges AS
(
    -- Find everyone and determine number of rows
    SELECT
        UP.MemberID
    ,   count(1) AS rc
    FROM 
        dbo.Member AS M
        UNPIVOT
        (
        ColumnValue for ColumnName in (AGEQ1, AGEQ2, AGEQ3)
        ) AS UP
    GROUP BY
        UP.MemberID
)
, NoAge AS
(
    -- Account for those that didn't show up
    SELECT M.MemberID
    FROM
        dbo.Member AS M
    EXCEPT
    SELECT
        H.MemberID
    FROM
        HadAges AS H
)
, NUMBERS AS
(
    -- Allowable range is 1-6
    SELECT TOP 6
        ROW_NUMBER() OVER (ORDER BY (SELECT NULL))  AS TheCount
    FROM
        sys.all_columns AS SC
)
, COMBINATION AS
(
    -- Link those with rows to their count
    SELECT
        N.TheCount AS ChildCount
    ,   H.MemberID
    FROM
        NUMBERS AS N
        LEFT OUTER JOIN
            HadAges AS H
            ON H.rc = N.TheCount
    UNION ALL
    -- Deal with the unlinked
    SELECT
        0
    ,   NA.MemberID
    FROM
        NoAge AS NA
)
SELECT
    C.ChildCount
,   COUNT(C.MemberID) AS Instances
FROM
    COMBINATION AS C
GROUP BY
    C.ChildCount;

【讨论】:

    【解决方案3】:

    试试这个:

    select id, a+b+c+d+e+f 
      from ( select id,
                    case when age1 is null then 0 else 1 end a,
                    case when age2 is null then 0 else 1 end b,
                    case when age3 is null then 0 else 1 end c,
                    case when age4 is null then 0 else 1 end d,
                    case when age5 is null then 0 else 1 end e,
                    case when age6 is null then 0 else 1 end f
              from ages 
           ) as t
    

    请看这里的小提琴http://sqlfiddle.com/#!3/88020/1

    获取有孩子的人数

    select childs, count(*) as ct
      from (
             select id, a+b+c+d+e+f childs
               from
                   (
                    select
                          id,
                          case when age1 is null then 0 else 1 end a,
                          case when age2 is null then 0 else 1 end b,
                          case when age3 is null then 0 else 1 end c,
                          case when age4 is null then 0 else 1 end d,
                          case when age5 is null then 0 else 1 end e,
                          case when age6 is null then 0 else 1 end f
                      from ages ) as t
                   ) ct
       group by childs
       order by 1
    

    在 fiddle http://sqlfiddle.com/#!3/88020/24 看到它

    【讨论】:

    • 这看起来可以工作,但我怎么能得到一个总数。例如拥有 1 个孩子、2 个孩子等的总人数
    • 根据您的要求编辑了我的答案。
    • 你的回答更容易理解,也很有效,而且更简单,但很抱歉我已经接受了上面的答案,这也是正确的
    • @InvokeIT 没问题,很高兴能帮上忙。这对我来说已经足够好了。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-11
    • 1970-01-01
    相关资源
    最近更新 更多