根据父记录查找最新的子记录(有条件)

Find Latest Child Record (With Conditions) Per Parent Record

我有 2 个具有 parent/child 层次结构的表,我正在尝试为每个父记录提取最新子记录的 ID,而且还对正在提取的子记录应用了条件。

这是我的表格的样子:

-----------
| Quizzes |
-----------
| ID      | 
-----------
| 1       |
| 2       |
| 3       |
-----------

-------------------------------------
| QuizAttempts                      |
-------------------------------------
| ID | QuizID | AttemptedAt         |
-------------------------------------
| 1  | 1      | 2021-01-01 05:00:00 |
| 2  | 1      | 2021-01-01 08:30:00 |
| 3  | 2      | 2021-01-01 05:00:00 |
| 4  | 3      | 2021-01-01 07:00:00 |
| 5  | 3      | 2021-02-01 07:00:00 |
| 6  | 3      | 2021-03-01 07:00:00 |
-------------------------------------

现在,假设我想为从 2021-01-01 00:00:002021-01-01 23:59:59 尝试的每个 Quiz 提取最新 QuizAttempt 的 ID,看起来像这样:

------------------------------------------------
| QuizID | QuizAttemptID | AttemptedAt         |
------------------------------------------------
| 1      | 2             | 2020-01-01 08:30:00 |
| 2      | 3             | 2020-01-01 05:00:00 |
| 3      | 4             | 2020-01-01 07:00:00 |
------------------------------------------------

目前,我正在做一个自引用连接来比较 ID 以提取最新的 QC:

SELECT attempts1.ID
FROM QuizAttempts AS attempts1
LEFT OUTER JOIN QuizAttempts AS attempts2
ON (attempts1.QuizID = attempts2.QuizID
    AND attempts1.ID < attempts2.ID)
WHERE attempts2.ID IS NULL;

这适用于拉取最新的子记录。但是,当我添加日期范围条件时(比如添加 attempts1.AttemptedAt BETWEEN '2021-01-01 00:00:00' AND '2021-01-01 23:59:59'),我得到的结果是空的。

我建议在子查询中使用 window 函数:

SELECT qa.*
FROM (SELECT qa.*,
             ROW_NUMBER() OVER (PARTITION BY QuizID ORDER BY id DESC) as seqnum
      FROM QuizAttempts qa
      WHERE qa.attemptedat >= '2021-01-01' AND
            qa.attemptedat < '2021-01-02'
     ) qa
WHERE seqnum = 1;

请注意,日期运算更简单,无需处理时间分量。

编辑:

您还可以使用相关子查询:

SELECT qa.*
FROM QuizAttempts qa
WHERE qa.id = (SELECT MAX(qa2.id),
               FROM QuizAttempts qa2
               WHERE qa2.QuizID = qa.QuizID AND
                     qa2.attemptedat >= '2021-01-01' AND
                     qa2.attemptedat < '2021-01-02'
              ) qa;