SQL选择has_many关系的最新元素列

时间:2016-02-24 16:34:20

标签: mysql sqlite foreign-key-relationship

在我的项目中,我有一个tasks (id,name)表。我还有一个status_updates (id,task_id,user_id,status,created_at)表。

我想选择最新status_update等于特定状态的任务。

我无法弄清楚如何结合以下内容:

  1. 仅对每项任务使用最新的status_update。
  2. 过滤掉状态正确的status_updates。
  3. 将其包含在INNER JOIN中,以便最终结果是一组任务。
  4. 使用GROUP_BY时,​​似乎1.和2.相互抵消。一个例子:

    SELECT * FROM status_updates GROUP BY task_id ORDER created_at DESC
    

    仅返回每个任务的最新status_update。 但是,这个:

    SELECT * FROM status_updates WHERE status='1' GROUP BY task_id ORDER created_at DESC
    

    执行ORDER之前的WHERE,从而从状态正确的中返回,而不是最新的,只返回状态正确的

    我也尝试过使用HAVING,但由于它只适用于聚合列,我无法弄清楚如何正确使用它,或者它在这种情况下是否有用。

    我正在使用Ruby on Rails,所以我想在MySQL和SQLite上都有答案。

1 个答案:

答案 0 :(得分:3)

使用子查询:

SELECT
    T.id,
    T.name,
    SU.status
FROM
    Tasks T
INNER JOIN (SELECT task_id, MAX(created_at) AS max_created_at FROM Status_Updates GROUP BY task_id) SQ ON SQ.task_id = T.id
INNER JOIN Status_Updates SU ON
    SU.task_id = SQ.task_id AND
    SU.created_at = SQ.max_created_at
WHERE
    SU.status = '1'

使用窗口函数和CTE(虽然目前RDBMS不支持,但它们很多,可能在将来)。这个有一个优点,它可以更好地处理关系:

WITH MyCTE AS
(
    SELECT
        T.id,
        T.name,
        SU.status,
        ROW_NUMBER OVER(PARTITION BY T.id ORDER BY SU.created_at DESC, id DESC) AS row_num
    FROM
        Tasks T
    INNER JOIN Status_Updates SU ON SU.task_id = T.id
)
SELECT
    id,
    name,
    status
FROM
    MyCTE
WHERE
    row_num = 1