[SQL][нуб] Упростить запрос MySQL
select kv1.key, kv1.value
from keyvalue kv1
left join keyvalue kv2 on kv1.key = kv2.key and kv2.date > kv1.date and kv2.date <= GivenDate
where kv2.date is null and kv1.date <= GivenDate
На тестовой таблице этот запрос показал 0.0189 секунды против 0.0064 изначальных.
он есть?
начальный вариант все равно лучше должен быть
Нет и это странно
начальный вариант все равно лучше должен бытьЯ просто подумал, что было бы классно, если можно заюзать какую-то специальную агрегатную функцию.
Как-то так MAX_BY_OTHER_FIELD(value, date). Выбрать значение в поле value, где максимальное date. Такое было бы абсудром, если date не уникально в группировке по key, а тут вроде бы "рукой подать" до value, когда делаем MAX(date). Надеюсь вы меня полняли.
юзать какую-то специальную агрегатную функцию.Я мог бы тебе по MSSQL посоветовать, но MySQL плохо знаю. До появления аналитических функций твой начальный вариант был оптимальным, но в мускуле их вроде нет до сих пор. Может еще что есть - не знаю
Как-то так MAX_BY_OTHER_FIELD(value, date). Выбрать значение в поле value, где максимальное date. Такое было бы абсудром, если date не уникально в группировке по key, а тут вроде бы "рукой подать" до value, когда делаем MAX(date). Надеюсь вы меня полняли.
Я мог бы тебе по MSSQL посоветовать, но MySQL плохо знаю. До появления аналитических функций твой начальный вариант был оптимальным, но в мускуле их вроде нет до сих пор. Может еще что есть - не знаюУ нас используется MySQL, к сожалению. А интересно, в Postgre есть такие функции?
есть
1. Есть ли индекс на key, date?
2. Сколько строк в таблице? сколько уникальных значений key?
3. Что не устраивает? твой запрос во многих случаях будет оптимальным, в чём потребность переписывать запрос?
Несколько вопросов:1. Уже писал, на тестовой таблице не было. Исправил. На рабочих таблицах есть.
1. Есть ли индекс на key, date?
2. Сколько строк в таблице? сколько уникальных значений key?
3. Что не устраивает? твой запрос во многих случаях будет оптимальным, в чём потребность переписывать запрос?
2. По-разному. От сотен до миллионов. Уникальных key явно больше, чем уникальных date в пределах одного key. Примерно, как правило, их количество = количество записей в таблице / 5 - 20.
3. Этот запрос чаще всего используется как вложенный, и практически как таблица среза значений на определенную дату. Я понимаю, когда в соединении таблиц необходимо получить значения на разные даты в разных строках, то там по-другому никак. Сейчас полетят какашки, но я работал с 1Ской и там такие срезы были реализованы виртуальными таблицами, которые просто летали. Но там, опять же, MSSQL. На Postgre все очень жутко тормозило. Т.к. такой запрос используется часто, хотелось бы использовать оптимальное решение.
я работал с 1Ской и там такие срезы были реализованы виртуальными таблицами
Это называется materialized view. В MySQL их нет.
Этот запрос чаще всего используется как вложенный, и практически как таблица среза значений на определенную дату.Может завести такую таблицу и просто заполнять её перед запросом?
Может завести такую таблицу и просто заполнять её перед запросом?Так и делаю, если есть повторы. Но чаще всего их нет. Смысла во временной таблице не вижу.
Я мог бы тебе по MSSQL посоветовать, но MySQL плохо знаю. До появления аналитических функций твой начальный вариант был оптимальным, но в мускуле их вроде нет до сих пор. Может еще что есть - не знаюня:
вариант 1 читерский:
SELECT key, valueно так лучше не делать - тут закладываешься на знание того, как оно внутри работает.
FROM (SELECT key, value
FROM keyvalue
WHERE dste < GivenDate
ORDER BY date DESC) t
GROUP BY key
вариант 2:
SELECT key, valueмне сегодня отгул дали - проверить не могу, но как-то так должно выглядеть
FROM (SELECT key, value
FROM keyvalue
WHERE date < GivenDate
ORDER BY date DESC) t
WHERE if (@previous = key, -1, @previous := key) <> -1
Я просто подумал, что было бы классно, если можно заюзать какую-то специальную агрегатную функцию.Вообще в мускуле такого нет, но симулировать можно:
Как-то так MAX_BY_OTHER_FIELD(value, date).
Вариант №3, наркоманский:
GROUP_CONCAT - оконная функция "для бедных" ^_^
SELECT key, LEFT(v, LOCATE('^', v value
FROM (SELECT key, GROUP_CONCAT(value ORDER BY date DESC SEPARATOR '^') v
FROM keyvalue
WHERE date < GivenDate
GROUP BY key) t
Если value меняется часто, будет работать долго и может упереться в group_concat_max_len.
Второй вариант самый интересный, спасибо. Потестируем.
Оставить комментарий
IG_rok777
Есть таблица (keyvalue)(date,key) - уникальны в пределах всей таблицы.
Задача - получить значения ключей на определенную дату (GivenDate). Т.е. берем по каждому ключу запись с максимальным date, до GivenDate.
Я делаю это таким запросом:
Как можно его упростить?