我有一个定期报告状态的组件列表。
我想编写一个查询来查找按组件分组的最新状态列表。
通常我会使用此问题的接受答案所描述的解决方案:MySQL order by before group by
但是每秒可以报告多个状态,因此无法保证我将检索最新的状态。因此,我想找到具有最新时间戳的状态,如果是重复时间戳,则查找具有最高时间戳的状态。
理想情况下,我希望得到如下查询:
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。
是否有人遇到类似问题并找到解决方案?
答案 0 :(得分:1)
您可以使用变量来模拟
ROW_NUMBER() OVER (PARTITION BY component_id
ORDER BY `timestamp` DESC, component_status_id DESC)
窗口功能:
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
的记录。
答案 1 :(得分:0)
它不能提供正确的结果,因为order by在group 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;
答案 2 :(得分:0)
我最终使用以下查询来解决我的问题:
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和timestamp上的复合索引,查询是即时的。