SQL中的交叉表查询,用于比较和添加列

时间:2016-09-29 15:56:22

标签: sql sql-server crosstab

我在sql server中有一个包含三列的表:“date”,“noon”和“3pm”。第一栏是不言自明的,但后两个栏目根据他们到达的时间在会场中包含演讲嘉宾的姓名。我想编写一个交叉表查询,将发言人姓名写入列标题,并计算发言人在该日期发言的次数。

实施例

Date   | Noon   |  3pm
092916 | Tom    | <null>
092816 | Dick   |  Tom 
092716 | <null> |  Suzy 

期望输出

Date   | Dick   |  Tom   |  Suzy
092916 | <null> |   1    | <null> 
092816 |  1     |   1    | <null>
092716 | <null> | <null> |   1

如果我只选择一次并将计数放入值类别中,我可以使用交叉表查询轻松完成此操作,但是我在多次合并时遇到问题,这样我就可以准确计算谁在说话了那一天。

2 个答案:

答案 0 :(得分:0)

您可以使用此查询:

select *
from   (
        select   date, noon as speaker, count(*) as times
        from     events
        group by date, noon
        union all 
        select   date, [3pm], count(*)
        from     events
        group by date, [3pm]
       ) as u
pivot  (
        sum(times)
        for speaker in ([Dick], [Tom], [Suzy])
       ) as piv
order by date desc;

...它为每个单元格提供一个计数(null,1或2):

Date   | Dick   |  Tom   |  Suzy
092916 | <null> |   1    | <null> 
092816 |   1    |   1    | <null>
092716 | <null> | <null> |   1

答案 1 :(得分:0)

您可以动态构建查询。

这将为在中午或下午3点列中找到的每个名称创建一个count(case)语句。类似于COUNT(CASE WHEN 'Dick' IN ([Noon],[3pm]) THEN 1 END) as [Dick]

DECLARE @speakers NVARCHAR(MAX),
        @sql NVARCHAR(MAX)

SET @speakers = STUFF((
    SELECT  ',COUNT(CASE WHEN ''' + [Name] + ''' IN ([Noon],[3pm]) THEN 1 END) as ' + QUOTENAME([Name])
    FROM    (SELECT [Noon] AS [Name] FROM Table1
             UNION ALL SELECT [3pm] FROM Table1) t
    GROUP BY t.Name 
    FOR XML PATH('')
), 1, 1, '')

SET @sql = N'SELECT Date, ' + @speakers + ' FROM Table1 GROUP BY Date'

--Print @sql to see what's going on
EXEC(@sql)