tsql PIVOT函数

时间:2011-07-18 17:46:37

标签: tsql

需要以下查询的帮助:

当前数据格式:

StudentID      EnrolledStartTime          EnrolledEndTime

1              7/18/2011 1.00 AM          7/18/2011 1.05 AM
2              7/18/2011 1.00 AM          7/18/2011 1.09 AM
3              7/18/2011 1.20 AM          7/18/2011 1.40 AM
4              7/18/2011 1.50 AM          7/18/2011 1.59 AM
5              7/19/2011 1.00 AM          7/19/2011 1.05 AM
6              7/19/2011 1.00 AM          7/19/2011 1.09 AM
7              7/19/2011 1.20 AM          7/19/2011 1.40 AM
8              7/19/2011 1.10 AM          7/18/2011 1.59 AM

我想计算EnrolledEndTime和EnrolledStartTime之间的时差,并将其与15分钟的差异以及当时注册的学生数量进行分组。

预期结果:

Count(StudentID)   Date    0-15Mins  16-30Mins 31-45Mins 46-60Mins

4               7/18/2011   3           1         0             0

4               7/19/2011   2           1         0             1

我可以使用PIVOT功能的组合来实现所需的结果。任何指针都会有所帮助。

3 个答案:

答案 0 :(得分:0)

创建一个表变量/临时表,其中包含原始表中的所有列,以及一行将行标记为0,16,31或46的列。然后

SELECT * FROM 临时表名 PIVOT(计数(StudentID)FOR 新列名(0,16,31,46)。

这应该让你非常接近。

答案 1 :(得分:0)

这是可能的(只需在此处查看基本的数据透视说明:http://msdn.microsoft.com/en-us/library/ms177410.aspx),但您使用数据透视表时遇到的一个问题是您需要提前知道要转入的列。

例如,你提到0-15,16-30等等,但实际上,你不知道有些学生可能需要多长时间 - 有些可能需要24小时,或者你的整个会话超时,或者你有什么。

因此,为了缓解这个问题,我建议将最后一列作为一个包罗万象,标记为“> 60”。

除此之外,只需在此表上选择,选择学生ID,日期和CASE语句,您就拥有了完成工作所需的一切。

CASE WHEN date2 - date1 < 15 THEN '0-15' WHEN date2-date1 < 30 THEN '16-30'...ELSE '>60' END.

答案 2 :(得分:0)

我有一个旧版本的ms sql server不支持pivot。我写了sql来获取数据。我不能测试枢轴,所以我尽我所能,无法测试枢轴部分。 sql的其余部分将为您提供数据透视表的确切数据。如果你接受null而不是0,它可以写得更简单,你可以跳过“with a ...”中定义的“a subselect”部分。

declare @t table (EnrolledStartTime datetime,EnrolledEndTime datetime)
insert @t values('2011/7/18 01:00',  '2011/7/18 01:05')
insert @t values('2011/7/18 01:00',  '2011/7/18 01:09')
insert @t values('2011/7/18 01:20',  '2011/7/18 01:40')
insert @t values('2011/7/18 01:50',  '2011/7/18 01:59')
insert @t values('2011/7/19 01:00',  '2011/7/19 01:05')
insert @t values('2011/7/19 01:00',  '2011/7/19 01:09')
insert @t values('2011/7/19 01:20',  '2011/7/19 01:40')
insert @t values('2011/7/19 01:10',  '2011/7/19 01:59')

;with a 
as
(select * from
(select distinct dateadd(day, cast(EnrolledStartTime as int), 0) date from @t) dates
cross join 
(select '0-15Mins' t,  0 group1 union select '16-30Mins',  1 union select '31-45Mins',  2 union select '46-60Mins',  3) i) 
, b as 
(select (datediff(minute, EnrolledStartTime, EnrolledEndTime )-1)/15 group1, dateadd(day, cast(EnrolledStartTime as int), 0) date
from @t)
select count(b.date) count, a.date, a.t, a.group1 from a
left join b 
on a.group1 = b.group1
and a.date = b.date 
group by a.date, a.t, a.group1
-- PIVOT(max(date)  
-- FOR group1
-- in(['0-15Mins'], ['16-30Mins'], ['31-45Mins'], ['46-60Mins'])AS p