【问题标题】:How do I search a partitioned window function in MSSQL如何在 MSSQL 中搜索分区窗口函数
【发布时间】:2021-12-18 19:48:45
【问题描述】:

场景: 与大学确定学生的第一堂课,并确定他们在通过第一堂课后是否在第一堂课结束后的一年内通过了第二堂课(连续)。如果学生在第一节课结束后的 1 年内没有连续通过第二节课,他们是否在同一时间段内通过了任何其他课程,例如?三、四、五班。

来自场景第一部分的问题很容易回答,使用lead() 函数将下一个连续的类信息拉到与第一类相同的行。但是,我无法找到确定学生是否在指定时间范围内(即第一节课结束后的 1 年内)通过任何课程的最佳方法。

我的问题: 有没有办法在由lead() 函数创建的分区中执行查找/搜索? 要么 基于及格成绩创建一个额外的聚合查询并使用 WHERE EXISTS 根据上述日期范围和适当的键连接回主表是否更好?

感谢您的观看...

【问题讨论】:

  • 这看起来很像您在寻求家庭作业帮助。此类问题必须包括您迄今为止为解决该问题所做的工作的总结,以及您在解决该问题时遇到的困难的描述。 What topics can I ask about here? 到目前为止,您自己尝试过什么回答这个问题?您阅读的文章/文档不理解怎么办?您可以在常见问题解答中找到有关如何提出家庭作业问题的更多信息:How do I ask and answer homework questions?
  • 即使不是作业,我们也需要看到minimal reproducible example,这对于SQL问题意味着我们需要样本数据和预期输出,最好是CREATEINSERT语句
  • 请提供足够的代码,以便其他人更好地理解或重现问题。
  • 感谢您的反馈。我并不想弄不清楚,我会添加一些示例代码和预期的输出以更好地通知。再次感谢您的反馈。这不是一个家庭作业问题:-)

标签: sql sql-server tsql window-functions


【解决方案1】:

确实这个问题不是很清楚。所以我猜测并想出了这个。

CREATE TABLE Class (
    Id        int   NOT NULL PRIMARY KEY IDENTITY(1, 1),
    ExamDate  date  NOT NULL,
    PassMark  float NOT NULL
)

CREATE TABLE Thing (
    Id        int   NOT NULL PRIMARY KEY IDENTITY(1, 1),
    StudentId int   NOT NULL,
    ClassId   int   NOT NULL,
    Score     float     NULL,

    CONSTRAINT Thing_FK_Class FOREIGN KEY (ClassId) REFERENCES Class(Id)
)

;
WITH ctePasses AS (
    -- Get the passes and order them.
    SELECT t.*, c.ExamDate,
        ROW_NUMBER() OVER (PARTITION BY StudentId ORDER BY c.ExamDate) AS n
    FROM Thing t
        INNER JOIN Class c ON t.ClassId = c.Id
    WHERE ISNULL(t.Score, 0) >= c.PassMark
),
cteIntermediateFails AS (
    -- For every student that has a pass get the number of fails that come after it until either the end of the next pass.
    SELECT t.StudentId, p.n, COUNT(*) AS IntermediateFails
    FROM Thing t
        INNER JOIN Class c ON t.ClassId = c.Id
        INNER JOIN ctePasses p ON t.StudentId = p.StudentId
        LEFT JOIN ctePasses q ON p.StudentId = q.StudentId AND p.n + 1 = q.n        
    WHERE c.ExamDate > p.ExamDate AND c.ExamDate < q.ExamDate
    GROUP BY t.StudentId, p.n
)
SELECT p1.StudentId, p1.ExamDate, p2.ExamDate, f.IntermediateFails
FROM ctePasses p1
    LEFT JOIN ctePasses p2 ON p1.StudentId = p2.StudentId AND p2.n = p1.n + 1
    LEFT JOIN cteIntermediateFails f ON p1.StudentId = f.StudentId AND p1.n = f.n
WHERE p1.n = 1

使用 CTE 而不是子查询让我可以在第二个中使用第一个。

【讨论】:

    猜你喜欢
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-01
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多