【问题标题】:How to list all months that have a requirement in SQL Server?如何在 SQL Server 中列出所有有要求的月份?
【发布时间】:2010-12-08 23:43:54
【问题描述】:

假设我有 3 张桌子:

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...

感谢您的帮助。

【问题讨论】:

  • 每个月的“monthly_assignments_required”是否相同?对我来说,您的RequiredAssignments 表上似乎缺少一个“月份”或类似的东西......或者您怎么知道每个学生类型在给定月份有多少作业??
  • 总是一样的......类型 1 的学生总是必须每月提交 4 份作业,类型 2 的学生总是每月提交 3 份作业,依此类推。
  • 你能告诉我们你的查询到目前为止是什么样子吗?
  • 您想要将月份作为交叉表之类的列,还是想要一个行列表?前者仅适用于单个学生查询。
  • 绝对是一个行列表,这最终将不得不生成一个 SSRS 报告,并且交叉表在那里不会有太大用处。

标签: sql sql-server tsql


【解决方案1】:

您需要创建一个数字表。

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)

【讨论】:

  • 谢谢。这就是我一直在走的路线。完成后我会发布我的想法,但这肯定会有所帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 2015-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多