我有一个带有星期范围的表(周数,开始日期,结束日期)和一个带有教程日期的表(用于编写导师(老师ID,tutorial_date,教程类型(A或B))。
我想创建两个查询,以显示顶部上方的星期范围(第1周,第2周),并在侧面显示该教师的姓名,并在该周的每个区块的该星期的日期范围内列出该数目的“A”类型的教程。
结果应如下所示:
类型“A”的教程数
Tutor|Week One|Week Two|Week Three|Week Four|Total
Joe | 3 | 5 | 7 | 8 | 23
Sam | 2 | 4 | 3 | 8 | 17
这意味着Joe在第一周完成了3个教程,第二周完成了五个教程,第三周完成了7个教程,第四周完成了8个教程。
第二个查询应显示教程类型“A”和类型“B”的总计
Tutor|Week One|Week Two|Week Three|Week Four|Total |
Joe | 3/1 | 5/3 | 7/2 | 8/2 | 23/8 |
Sam | 2/3 | 4/4 | 3/2 | 8/3 | 17/12 |
在这里,在第一周,乔完成了3个类型A的教程和1个类型B的教程。
教程的样本表数据(第一周)
Tutor | Tutorial_ID | Tutorial Date |Type|
------------------------------------------
Joe | 1 | 2011-01-01 | A |
Joe | 2 | 2011-01-02 | A |
Joe | 3 | 2011-01-03 | A |
Joe | 4 | 2011-01-03 | B |
Sam | 5 | 2011-01-01 | A |
Sam | 6 | 2011-01-02 | A |
Sam | 7 | 2011-01-03 | B |
周表如下所示:
weekNumber |startDate |endDate
1 |2011-01-01|2011-01-15
我想在SQL Server 2005中生成
最佳答案
有几种方法可以做到这一点。
对于查询一个,您只需要在类型'A'上进行PIVOT
即可,那么您只需做一个PIVOT
select *
from
(
select w1.tutor
, w1.type
, wk.weeknumber
from w1
inner join wk
on w1.tutorialdate between wk.startdate and wk.enddate
where w1.type = 'a'
) x
pivot
(
count(type)
for weeknumber in ([1])
)p
通过演示查看SQL Fiddle
或者,您可以将
Count()
与CASE
语句一起使用。select w1.tutor
, COUNT(CASE WHEN w1.type = 'A' THEN 1 ELSE null END) [Week One]
from w1
inner join wk
on w1.tutorialdate between wk.startdate and wk.enddate
group by w1.tutor
参见SQL Fiddle with Demo
但是对于第二个查询,我只需要使用
Count()
和CASE
select w1.tutor
, Cast(COUNT(CASE WHEN w1.type = 'A' AND wk.weeknumber = 1 THEN 1 ELSE null END) as varchar(10))
+ ' / '
+ Cast(COUNT(CASE WHEN w1.type = 'B' AND wk.weeknumber = 1 THEN 1 ELSE null END) as varchar(10)) [Week One]
, Cast(COUNT(CASE WHEN w1.type = 'A' AND wk.weeknumber = 2 THEN 1 ELSE null END) as varchar(10))
+ ' / '
+ Cast(COUNT(CASE WHEN w1.type = 'B' AND wk.weeknumber = 2 THEN 1 ELSE null END) as varchar(10)) [Week Two]
from w1
inner join wk
on w1.tutorialdate between wk.startdate and wk.enddate
group by w1.tutor
参见SQL Fiddle with Demo
编辑为AndriyM指出,第二个可以使用PIVOT完成,这是第二个查询的解决方案:
SELECT *
FROM
(
select distinct w1.tutor
, wk.weeknumber
, left(total, len(total)-1) Totals
FROM w1
inner join wk
on w1.tutorialdate between wk.startdate and wk.enddate
CROSS APPLY
(
SELECT cast(count(w2.type) as varchar(max)) + ' / '
from w1 w2
inner join wk wk2
on w2.tutorialdate between wk2.startdate and wk2.enddate
WHERE w2.tutor = w1.tutor
AND wk2.weeknumber = wk.weeknumber
group by w2.tutor, wk2.weeknumber, w2.type
FOR XML PATH('')
) D ( total )
) x
PIVOT
(
min(totals)
for weeknumber in ([1], [2])
) p
参见SQL Fiddle with Demo
关于sql-server-2005 - 将内容放入SQL Server 2005中的日期范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5008560/