查找每个组件的最新记录 MySQL
Find most recent record MySQL per component
我有一个定期报告状态的组件列表。
我想编写一个查询来查找按组件分组的最新状态列表。
通常我会使用这个问题的公认答案所描述的解决方案:MySQL order by before group by
但是每秒可能会报告多个状态,因此无法保证我会检索到最新的状态。因此,我想找到具有最新时间戳的状态,在重复时间戳的情况下,具有最高 PK 的状态。
理想情况下,我希望有如下查询:
SELECT *
FROM component_status
ORDER BY component_status.timestamp DESC, component_status.component_status_id DESC
GROUP BY component_status.component_id;
但是您不能在 ORDER BY 之后执行 GROUP BY。
有没有人遇到过类似的问题并找到了解决方案?
它不会提供正确的结果,因为 order by 在 group by 之后工作,为此你可以先在子查询中获得 order by 结果然后你可以对它们进行分组。
例如-
select field1, field2 from (SELECT field1,field2,...,component_status.component_id
FROM component_status
ORDER BY component_status.timestamp DESC, component_status.component_status_id DESC) a
GROUP BY a.component_id;
可以使用变量来模拟
ROW_NUMBER() OVER (PARTITION BY component_id
ORDER BY `timestamp` DESC, component_status_id DESC)
window函数:
SELECT component_id, component_status_id, `timestamp`
FROM (
SELECT component_id, component_status_id, `timestamp`,
@row_number:=
IF (@cid <> component_id,
IF (@cid := component_id, 1, 1),
IF (@cid := component_id, @row_number + 1, @row_number + 1)) AS rn
FROM component_status
CROSS JOIN (SELECT @row_number:= 0, @cid := -1) vars
ORDER BY `timestamp` DESC, component_status_id DESC ) t
WHERE rn = 1
外部查询中的 rn=1
根据 component_id
选择最近的记录。如果有两个或多个记录具有相同的 timestamp
,则将选择具有最大 component_status_id
的记录。
我最终通过以下查询解决了我的问题:
SELECT
component_status.*
FROM
component_status
JOIN
(SELECT
MAX(component_status_id) AS component_status_id
FROM
component_status
JOIN
(SELECT
MAX(timestamp) AS timestamp, component_id
FROM
component_status
WHERE
timestamp <= NOW()
GROUP BY component_id) AS most_recent_status
USING (component_id)
WHERE component_status.timestamp = most_recent_status.timestamp
GROUP BY component_id) AS most_recent_status
USING (component_status_id)
使用 component_id 上的复合索引和时间戳,查询是即时的。
我有一个定期报告状态的组件列表。
我想编写一个查询来查找按组件分组的最新状态列表。
通常我会使用这个问题的公认答案所描述的解决方案:MySQL order by before group by
但是每秒可能会报告多个状态,因此无法保证我会检索到最新的状态。因此,我想找到具有最新时间戳的状态,在重复时间戳的情况下,具有最高 PK 的状态。
理想情况下,我希望有如下查询:
SELECT *
FROM component_status
ORDER BY component_status.timestamp DESC, component_status.component_status_id DESC
GROUP BY component_status.component_id;
但是您不能在 ORDER BY 之后执行 GROUP BY。
有没有人遇到过类似的问题并找到了解决方案?
它不会提供正确的结果,因为 order by 在 group by 之后工作,为此你可以先在子查询中获得 order by 结果然后你可以对它们进行分组。
例如-
select field1, field2 from (SELECT field1,field2,...,component_status.component_id
FROM component_status
ORDER BY component_status.timestamp DESC, component_status.component_status_id DESC) a
GROUP BY a.component_id;
可以使用变量来模拟
ROW_NUMBER() OVER (PARTITION BY component_id
ORDER BY `timestamp` DESC, component_status_id DESC)
window函数:
SELECT component_id, component_status_id, `timestamp`
FROM (
SELECT component_id, component_status_id, `timestamp`,
@row_number:=
IF (@cid <> component_id,
IF (@cid := component_id, 1, 1),
IF (@cid := component_id, @row_number + 1, @row_number + 1)) AS rn
FROM component_status
CROSS JOIN (SELECT @row_number:= 0, @cid := -1) vars
ORDER BY `timestamp` DESC, component_status_id DESC ) t
WHERE rn = 1
外部查询中的 rn=1
根据 component_id
选择最近的记录。如果有两个或多个记录具有相同的 timestamp
,则将选择具有最大 component_status_id
的记录。
我最终通过以下查询解决了我的问题:
SELECT
component_status.*
FROM
component_status
JOIN
(SELECT
MAX(component_status_id) AS component_status_id
FROM
component_status
JOIN
(SELECT
MAX(timestamp) AS timestamp, component_id
FROM
component_status
WHERE
timestamp <= NOW()
GROUP BY component_id) AS most_recent_status
USING (component_id)
WHERE component_status.timestamp = most_recent_status.timestamp
GROUP BY component_id) AS most_recent_status
USING (component_status_id)
使用 component_id 上的复合索引和时间戳,查询是即时的。