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