计算数据是否存在于一行中

时间:2013-11-14 03:27:12

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

嘿伙计们,我有以下示例数据,我想查询。

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的答案,但我希望能够计算数据的其他列

希望这很好,很清楚,并提前感谢你

3 个答案:

答案 0 :(得分:2)

如果所有列都是整数,则可以利用整数数学 - 除非值为NULL,否则将列除以自己将产生1,在这种情况下,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 :(得分:1)

试试这个:

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

在小提琴http://sqlfiddle.com/#!3/88020/24

中查看

答案 2 :(得分:1)

我会考虑使用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;