Мой стол:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
3 | 10 | 03/03/2009 | john | 300
4 | 11 | 03/03/2009 | juliet | 200
6 | 12 | 03/03/2009 | borat | 500
7 | 13 | 24/12/2008 | borat | 600
8 | 13 | 01/01/2009 | borat | 700
Мне нужно выбрать для каждого отдельного home
максимального значения datetime
.
Результат будет:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
8 | 13 | 01/01/2009 | borat | 700
Я пытался:
-- 1 ..by the MySQL manual:
SELECT DISTINCT
home,
id,
datetime AS dt,
player,
resource
FROM topten t1
WHERE datetime = (SELECT
MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC
Не работает Result-set имеет 130 строк, хотя база данных содержит 187. Результат содержит несколько дубликатов home
.
-- 2 ..join
SELECT
s1.id,
s1.home,
s1.datetime,
s1.player,
s1.resource
FROM topten s1
JOIN (SELECT
id,
MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
ON s1.id = s2.id
ORDER BY datetime
Нет. Дает все записи.
-- 3 ..something exotic:
С различными результатами.
id
,player
иresource
не-макс строки для данного дома , т.е. для дома = 10 вы можете получить:3 | 10 | 04/03/2009 | john | 300
Другими словами , это не гарантирует , что все столбец строки в результирующем будет принадлежать до макс (дата / время) для данного дома.Самое быстрое
MySQL
решение, без внутренних запросов и безGROUP BY
:Пояснение :
Соедините таблицу с самим собой, используя
home
столбец. ИспользованиеLEFT JOIN
гарантирует, что все строки из таблицыm
появятся в наборе результатов. Те, у кого нет совпадений в таблице,b
будут иметьNULL
s для столбцовb
.Другое условие в
JOIN
запросе сопоставляет только те строки,b
которые имеют большее значение вdatetime
столбце, чем строка изm
.Используя данные, опубликованные в вопросе,
LEFT JOIN
получим следующие пары:Наконец, в
WHERE
предложении сохраняются только те пары, которые имеютNULL
s в столбцахb
(они отмечены*
в таблице выше); это означает, что из-за второго условия вJOIN
предложении выбранная строкаm
имеет наибольшее значение в столбцеdatetime
.Прочтите книгу « Антипаттерны SQL: как избежать ловушек программирования баз данных», чтобы узнать другие советы по SQL.
источник
SQLite
этом первая намного медленнее, чем версия La Voie, когда в сопоставляемом столбце нет индекса (т. Е. «Home»). (Протестировано с 24 тыс. Строк, что дает 13 тыс. Строк)home
иdatetime
иdatetime
максимальный для этого частностиhome
?ON
предложении. Fe ,... ON ... AND m.id < b.id
чтобы сохранить самую последнюю запись (один с самым большимid
) , когда две строки имеют одинаковые значения вhome
иdatetime
столбцы , и это является максимальнойdatetime
.Вот версия T-SQL :
РЕДАКТИРОВАТЬ
К сожалению, в MySQL нет функции RANK () OVER.
Но его можно эмулировать, см. Эмуляция аналитических функций (AKA Ranking) с MySQL .
Итак, это версия MySQL :
источник
Это будет работать, даже если у вас есть две или более строки для каждой
home
с равнымиDATETIME
:источник
WHERE ti.home = t1.home
Вы можете объяснить синтаксис?select
запрос, имеющий строкуWHERE ti.home = t1.home
, не нуждается вFROM
предложении, которое определяетt1
. Так как это используется?Я думаю, что это даст вам желаемый результат:
НО, если вам нужны и другие столбцы, просто сделайте соединение с исходной таблицей (проверьте
Michael La Voie
ответ)С наилучшими пожеланиями.
источник
Так как люди, кажется, продолжают сталкиваться с этой темой (дата комментария колеблется от 1,5 года), не намного проще:
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
Функции агрегирования не нужны ...
Приветствия.
источник
Вы также можете попробовать это, и для больших таблиц производительность запросов будет лучше. Это работает, когда не более двух записей для каждого дома и их даты разные. Лучший общий запрос MySQL - тот, что был от Michael La Voie выше.
Или в случае Postgres или тех БД, которые предоставляют аналитические функции, попробуйте
источник
SQLite
этом первая намного медленнее, чем версия La Voie, когда в сопоставляемом столбце нет индекса (т. Е. «Home»).Это работает на Oracle:
источник
источник
Попробуйте это для SQL Server:
источник
источник
Вот версия MySQL, которая печатает только одну запись, в которой есть дубликаты MAX (datetime) в группе.
Вы можете проверить здесь http://www.sqlfiddle.com/#!2/0a4ae/1
Образец данных
Версия MySQL с пользовательской переменной
Outout принятых ответов
источник
Другой способ получить самую последнюю строку в группе, используя подзапрос, который в основном вычисляет ранг для каждой строки в группе, а затем отфильтровывает ваши последние строки, как с rank = 1.
DEMO
Вот визуальная демонстрация для ранга № для каждой строки для лучшего понимания
Вышеупомянутый запрос не будет выполнен и вернет более 1 строки для вышеуказанной ситуации. Чтобы скрыть эту ситуацию, понадобится другой критерий / параметр / столбец, чтобы решить, какую строку следует взять, которая попадает в вышеуказанную ситуацию. Просматривая пример набора данных, я предполагаю, что есть столбец первичного ключа,
id
который должен быть установлен на автоинкремент. Таким образом, мы можем использовать этот столбец, чтобы выбрать самую последнюю строку, настроив тот же запрос с помощьюCASE
оператора вродеDEMO
Выше запрос будет выбрать строку с самым высоким идентификатором среди тех же
datetime
значенийвизуальная демонстрация для ранга № для каждой строки
источник
Почему бы не использовать: SELECT home, MAX (datetime) AS MaxDateTime, плеер, ресурс из topten GROUP BY home Я что-то пропустил?
источник
expected
вывод в MySQL версии 5.6 иbefore
и я сильно сомневаюсь, что он будет вести себя иначе в MySQL версии 5.7 иafter
.Попробуй это
С уважением К
источник
max(datetime)
естьdatetime
. Не создаст ли это проблемы?datetime
выбрать самый высокий ?это запрос, который вам нужен:
источник
@Michae Принятый ответ будет работать нормально в большинстве случаев, но не получится, как показано ниже.
В случае, если было 2 строки с одинаковыми HomeID и Datetime, запрос возвратит обе строки, а не HomeID, как требуется, для этого добавьте Distinct в запрос, как показано ниже.
источник
Надеюсь, что приведенный ниже запрос даст желаемый результат:
источник