Помогите написать запрос: Путаница по порядку операций GROUP BY и ORDER BY - PullRequest
2 голосов
/ 25 октября 2008

У меня есть таблица с именем Info этой схемы:

int objectId;
int time;
int x, y;

В системе много избыточных данных, то есть objectId не УНИКАЛЬНО. Для каждого objectId может быть несколько записей time, x, y.

Я хочу получить список последней позиции каждого объекта. Я начал с этого запроса:

SELECT * FROM Info GROUP BY objectId

Это дало мне именно тот список, который я искал. Однако я также хочу получить только самые последние времена для каждого объекта, поэтому я попытался:

SELECT * FROM Info GROUP BY objectId ORDER BY time DESC

Это дало мне 1010 * спущенный список информации. Тем не менее, Я не думаю, что он сделал то, что я хочу - это вернуть мне самое последнее 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 ]

7 голосов
/ 25 октября 2008
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 & y уменьшится в любой точке временной шкалы.

6 голосов
/ 25 октября 2008

Один из способов - использовать подзапрос.

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

EDIT: добавлен DISTINCT для предотвращения дублирования строк, если один objectId имеет несколько записей с одним и тем же временем. Зависит от ваших данных, если это необходимо, автор вопроса отметил, что было много повторяющихся строк. ( добавлено Томалак )

1 голос
/ 25 октября 2008

Это довольно распространенный способ получения всей информации подряд для строки, являющейся частью группы.

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

За последние пару недель один и тот же вопрос задавался в разных формах пару раз. Я забыл, как были сформулированы вопросы.

1 голос
/ 25 октября 2008

Для чего это стоит, вот еще один способ получить желаемый результат. У меня появилась привычка делать подобные трюки за 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. GROUP BY не требуется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...