帮助编写查询:混淆GROUP BY和ORDER BY的操作顺序

时间:2008-10-25 18:06:03

标签: mysql sql database

我有一个名为Info of this schema的表:

int objectId;
int time;
int x, y;

系统中存在大量冗余数据 - 即objectId不是唯一的。对于每个objectId,可以有多个time, x, y条目。

我想检索每个对象的最新位置列表。我从这个问题开始:

SELECT * FROM Info GROUP BY objectId

这让我只是那种我正在寻找的名单。但是我想要获得每个Object的最新时间,所以我尝试了:

SELECT * FROM Info GROUP BY objectId ORDER BY time DESC

这给了我一个time下载的Infos列表。但是,我认为它不符合我的要求 - 这会为我返回每个对象的最新time, x, y

任何人都可以想象一个查询来做我想做的事吗?

更新我已经尝试了前三种解决方案,以了解它们在大约50,000个数据集的数据集上如何相互作用。结果如下:

-- NO INDEX: forever
-- INDEX: 7.67 s

SELECT a.*
FROM Info AS a
  LEFT OUTER JOIN Info AS b ON (a.objectId = b.objectId AND a.time < b.time)
WHERE b.objectId IS NULL;

-- NO INDEX: 8.05 s
-- INDEX: 0.17 s

select a.objectId, a.time, a.x, a.y
  from Info a,
       (select objectId, max(time) time from Info group by objectId) b
  where a.objectId = b.objectId and a.time = b.time;

-- NO INDEX: 8.30 s
-- INDEX: 0.18 s

SELECT A.time, A.objectId, B.x, B.y
FROM
(
   SELECT max(time) as time, objectId 
   FROM Info
   GROUP by objectId
) as A 
INNER JOIN Info B
   ON A.objectId = b.objectId AND A.time = b.time;

一定程度上,where似乎优于inner join

4 个答案:

答案 0 :(得分:7)

SELECT A.time, A.objectID, B.X, B.Y
FROM
(
   SELECT max(time) as time, objectID 
   FROM table
   GROUP by objectID
) as A 
INNER JOIN table B
   ON A.objectID = b.objectID AND A.Time = b.Time

投票者,解决方案将不起作用,如果x&amp; y在时间线的任何一点递减。

答案 1 :(得分:6)

一种方法是使用子查询。

select distinct a.objectID, a.time, a.x, a.y
  from Info a,
       (select objectID, max(time) time from Info group by objectID) b
  where a.objectID = b.objectID and a.time = b.time

编辑:添加DISTINCT以防止重复行,如果一个objectId具有同一时间的多个记录。如果有必要,取决于您的数据,问题作者提到有许多重复的行。 (Tomalak 添加)

答案 2 :(得分:1)

对于它的价值,这是获得理想结果的另一种方式。在习惯支持子查询之前,我养成了在MySQL 4.0天里做这样的技巧的习惯。

SELECT a.*
FROM Info AS a
  LEFT OUTER JOIN Info AS b ON (a.objectID = b.objectID AND a.time < b.time)
WHERE b.objectID IS NULL;

换句话说,向我展示没有其他行存在且具有相同objectID和更长时间的行。这自然地返回具有每个objectID的最大时间的行。不需要GROUP BY。

答案 3 :(得分:1)

这是获取行中所有信息的一种非常常见的方式,对于作为组的一部分的行。

Select Info.*
from Info
inner join
   (select ObjectId, max(time) as Latest
    from Info
    group by ObjectId)  I
on Info.ObjectId = I.ObjectID and Info.time = I.Latest

在过去的几周里,有几次以不同的形式提出同样的问题。我忘记了问题是如何措辞的。