2010-12-08 98 views
2

比方说,我有3个表:如何在SQL Server中列出所有需要的月份?

Student (
    student_id, 
    student_type_id, 
    start_date, 
    end_date 
) 

RequiredAssignments (
    student_type_id, 
    monthly_assignments_required 
) 

Assignment (
    student_id, 
    datecompleted 
) 

基本上,在RequiredAssignments表中,monthly_assignments_required场,指出有多少分配给定类型的每个学生必须在每个月把一个整数。

我想构建一个查询,列出学生,一个月,需要多少分配以及他们为每个学生转入的次数,每个学生在给定开始日期和结束日期之间的每个月。

我卡现在在得到与开始和结束日期(含)之间的,每月列出的student_id ...

感谢您的帮助。

+0

是“monthly_assignments_required”每个月的相同?对我来说,你好像在你的RequiredAssignments表中缺少一个“月”或类似的东西......或者你怎么知道每个学生类型在给定月份中有多少个作业? – 2010-12-08 14:50:07

+0

总是一样的......类型1的学生每个月都必须交4次作业,类型2将总是每个月交3次,等等等等。 – 2010-12-08 14:52:54

回答

2

您需要创建一个数字表。

CREATE TABLE dbo.Numbers 
(
n INT PRIMARY KEY 
); 


WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1), --2 
     E02(N) AS (SELECT 1 FROM E00 a, E00 b), --4 
     E04(N) AS (SELECT 1 FROM E02 a, E02 b), --16 
     E08(N) AS (SELECT 1 FROM E04 a, E04 b), --256 
     E16(N) AS (SELECT 1 FROM E08 a, E08 b) --65,536 
INSERT INTO dbo.Numbers 
SELECT TOP 10000 ROW_NUMBER() OVER (ORDER BY (SELECT 0)) 
FROM E16 

一旦你有了这个,你可以这样做(未经测试)

SELECT s.student_id, 
     DATEADD(MONTH,n-1,start_date) AS MonthStart, 
     COUNT(*) 
FROM Student s 
JOIN dbo.Numbers ON n <= (1 + DATEDIFF(MONTH,s.start_date, s.end_date)) 
LEFT JOIN Assignment a ON a.student_id = s.student_id and a.datecompleted >= DATEADD(MONTH,n-1,start_date) and a.datecompleted < DATEADD(MONTH,n,start_date) 
GROUP BY s.student_id, DATEADD(MONTH,n-1,start_date)