MySQL: получить самую последнюю запись

80

Как в таблице ниже получить только самую последнюю запись на id=1основе столбца входа, а не все 3 записи?

+----+---------------------+---------+
| id | signin              | signout |
+----+---------------------+---------+
|  1 | 2011-12-12 09:27:24 | NULL    |
|  1 | 2011-12-13 09:27:31 | NULL    |
|  1 | 2011-12-14 09:27:34 | NULL    |
|  2 | 2011-12-14 09:28:21 | NULL    |
+----+---------------------+---------+
шанс
источник

Ответы:

90

Используйте агрегат, MAX(signin)сгруппированный по идентификатору. Это будет список самых последних signinдля каждого id.

SELECT 
 id, 
 MAX(signin) AS most_recent_signin
FROM tbl
GROUP BY id

Чтобы получить всю отдельную запись, выполните INNER JOINподзапрос, который возвращает только MAX(signin)идентификатор.

SELECT 
  tbl.id,
  signin,
  signout
FROM tbl
  INNER JOIN (
    SELECT id, MAX(signin) AS maxsign FROM tbl GROUP BY id
  ) ms ON tbl.id = ms.id AND signin = maxsign
WHERE tbl.id=1
Майкл Берковски
источник
Вот что сработало на основе вашего первого ответа:SELECT id, MAX(signin) FROM tbl GROUP BY id WHERE id=1;
enchance
Я попытался реализовать второе решение (чтобы получить всю строку) в своей собственной ситуации, но всегда получаю пустой набор результатов
rantsh
Ответ @rantsh xQbert имел правильную версию того, что у меня изначально было выше, но я предпочитаю решение, которое я только что изменил.
Майкл Берковски
@MichaelBerkowski, вы имели в виду, что предпочитаете мое решение? Я был бы не против получить положительный голос за свой ответ, если это так
rantsh
1
@ranth А, я не заметил, что вы добавили нечто похожее на то, что я только что изменил, за исключением via USINGвместо явного ON. Вы получили +1 :)
Майкл Берковски
83
SELECT *
FROM   tbl
WHERE  id = 1
ORDER  BY signin DESC
LIMIT  1;

Очевидный показатель будет на (id), или индекс многоколончатого на (id, signin DESC).

Для удобства MySQL отсортировывает NULLзначения последними в порядке убывания. Это то, что вы обычно хотите, если могут быть NULLзначения: строка с последним ненулевым значением signin.

Чтобы NULLсначала получить значения:

ORDER BY signin IS NOT NULL, signin DESC

Связанный:

Стандарт SQL явно не определяет порядок сортировки NULLзначений по умолчанию . Поведение довольно сильно различается в разных СУБД. Видеть:

Но есть в NULLS FIRST/ NULLS LASTположении , определенное в стандарте SQL и поддерживается большинство основной СУБД, но не MySQL. Видеть:

Эрвин Брандштеттер
источник
5
Похоже, это самый чистый способ сделать это!
karancan
Рассмотрите возможность создания индекса для столбца входа, это значительно
ускорит
Используйте SELECT TOP 1 *и удалите LIMIT 1последнюю строку. при использовании SQL Server. Используйте указанное выше, если MySQL или Postgres.
jaredbaszler
Самый чистый. . . . . . . .
stigzler
Просто и чисто!
Джереми Сваггер
9

Основываясь на ответе @ xQbert, вы можете избежать подзапроса И сделать его достаточно общим для фильтрации по любому идентификатору

SELECT id, signin, signout
FROM dTable
INNER JOIN(
  SELECT id, MAX(signin) AS signin
  FROM dTable
  GROUP BY id
) AS t1 USING(id, signin)
болтовня
источник
Привет, как работает этот запрос и эффективнее, чем ответ xQbert? Оба запроса выполняются для меня примерно в одно и то же время, и я не понимаю, какая часть запроса используется вместо того, что обычно есть.
ZJS
3
Select [insert your fields here]
from tablename 
where signin = (select max(signin) from tablename where ID = 1)
xQbert
источник
1
SELECT * FROM (SELECT * FROM tb1 ORDER BY signin DESC) GROUP BY id;
user3044573
источник
1

У меня была аналогичная проблема. Мне нужно было получить последнюю версию перевода содержимого страницы, другими словами - получить ту конкретную запись, которая имеет наибольший номер в столбце версии. Поэтому я выбираю все записи, упорядоченные по версии, а затем беру первую строку из результата (с помощью предложения LIMIT).

SELECT *
FROM `page_contents_translations`
ORDER BY version DESC
LIMIT 1
Алесь
источник
1

Простой способ достичь

Я знаю, что это старый вопрос. Вы также можете сделать что-нибудь вроде

SELECT * FROM Table WHERE id=1 ORDER BY signin DESC

В приведенном выше примере запрос первой записи будет самой последней записью.

Только для одной записи вы можете использовать что-то вроде

SELECT top(1) * FROM Table WHERE id=1 ORDER BY signin DESC

Вышеуказанный запрос вернет только одну последнюю запись.

Ура!

Аджмал Джамил
источник