Укажите порядок сортировки для запроса GROUP BY для получения самой старой или самой новой записи для каждой группы. - PullRequest
2 голосов
/ 27 апреля 2010

Мне нужно получить самую последнюю запись для каждого устройства из таблицы журнала запросов на обновление. Устройство является уникальным в зависимости от комбинации его идентификатора оборудования и MAC-адреса. Я пытался сделать это с GROUP BY, но я не уверен, что это безопасно, поскольку похоже, что он просто возвращает «верхнюю запись» (независимо от того, что SQLite или MySQL считает, что это так).

Я надеялся, что на эту "верхнюю запись" можно будет намекнуть с помощью ORDER BY, но это не оказывает никакого влияния, поскольку оба следующих запроса возвращают одинаковые записи для каждого устройства, только в противоположном порядке :

SELECT extHwId,
       mac,
       created
  FROM upgradeRequest
 GROUP BY extHwId, mac
 ORDER BY created DESC

SELECT extHwId,
       mac,
       created
  FROM upgradeRequest
 GROUP BY extHwId, mac
 ORDER BY created ASC

Есть ли другой способ сделать это? Я видел несколько похожих постов, в которых были задействованы все субселекты. Если возможно, я бы хотел сделать это без подвыборов, так как я хотел бы научиться делать это без этого.

Ответы [ 3 ]

2 голосов
/ 27 апреля 2010

Попробуйте:

 SELECT extHwId, mac, MAX(created)
 FROM upgradeRequest
 GROUP BY extHwId, mac
1 голос
/ 27 апреля 2010

Вы не можете "получить самую последнюю запись " с помощью GROUP BY. GROUP BY объединяет много записей вместе, так что в итоге вы видите / извлекаете не реальные записи из таблицы, а «виртуальные» записи, созданные из одной или нескольких записей таблицы.

Если вам действительно нужна самая последняя запись для каждого устройства, вам нужно использовать подзапрос. Однако, если вы хотите узнать только дату самой последней записи для каждого устройства, вы можете использовать GROUP BY, поместив агрегат MAX вокруг созданного поля:

SELECT
    extHwId, 
    mac, 
    MAX(created)
FROM upgradeRequest
GROUP BY extHwId, mac
ORDER BY created ASC
0 голосов
/ 27 апреля 2010

Это должно сделать это ...

SELECT ur.extHwId,
       ur.mac,
       ur.created
 from upgradeRequest ur
  left outer join upgradeRequest ur2
   on ur2.extHwId = ur.extHwId
    and ur2.mac = ur.mac
    and ur2.Created > ur.Created  --  Join with all "later" entries
 where ur2.Created is null  --  Filter out all rows that have any later entries

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

SELECT ur.extHwId,
       ur.mac,
       ur.created
 from upgradeRequest ur
 where not exists (select 1
                    from upgradeRequest ur2
                    where ur2.extHwId = ur.extHwId
                     and ur2.mac = ur.mac
                     and ur2.Created > ur.Created)

Преимущество здесь состоит в том, что ядру базы данных нужно только найти 1 строку в подзапросе (в отличие от чтения всех строк в первую очередь), чтобы отфильтровать строку.

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