2015-06-23 31 views
2

我有一个定期报告状态的组件列表。查找最新记录每个组件的MySQL

我想编写一个查询来查找按组件分组的最新状态列表。

通常我会用被接受的答案对这个问题描述的解决方案: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。

有没有人有类似的问题,并找到了解决方案?

+0

我看不出你的问题与引用的问题有什么不同。 – Strawberry

+1

@Strawberry引用的帖子使用* single *列上的聚合来获取最近的记录。在这个问题中,最近的记录是由*两个*列确定的。 –

+0

@GiorgosBetsos当然,但原则保持不变。 – Strawberry

回答

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一个综合指数和时间戳查询是瞬间的。

0

它不会提供正确的结果,因为顺序是在组合之后进行的,因此您可以先通过子查询中的结果获得顺序,然后您可以对它们进行分组。

的示例 -

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; 
+0

我尝试过这样的事情,但有数百万和数百万条记录,而且速度非常慢并且效率低下(即使在编制索引时)。 – Fooble

+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的记录。

Demo here

+0

这看起来很有前途!我会试一试,让你知道它是怎么回事。 – Fooble