@frmax
человек

Как выполнить туже операцию 1 запросом?

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

Задача:
Есть таблица `course` (`currency` enum(‘usd’, ‘eur’, ...), `price` float, `created_at` datetime) с курсами валют. В таблицу идет запись, как только изменился курс, путем добавления новой записи в конец. Курс по одной валюте может не меняться несколько дней, а по другой изменяться каждую минуту. Необходимо вывести актуальный курс валют. Список валют заранее не известен.

Попытки
sqlfiddle.com/#!9/172f58/1

Код который делает что мне нужно
SELECT n.* 
FROM course n 
INNER JOIN (
SELECT id, MAX(created_at) AS created_at
  FROM course GROUP BY currency  
) AS max USING (created_at)
;


Структура
CREATE TABLE IF NOT EXISTS `course` (
  `id` int(6) unsigned NOT NULL,
  `price` int(3) unsigned NOT NULL,
  `currency` enum('usd', 'rub') NOT NULL,
  `created_at` datetime,
  PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `course` (`id`, `price`, `currency`, `created_at`) VALUES
  (1, 1, 'usd', CURDATE()),
  (2, 6, 'usd', date('2020-11-11')),
  (3, 3, 'usd', date('2020-12-11')),
  (4, 2, 'rub', date('2019-11-11')),
  (5, 66, 'rub', date('2020-11-14')),
  (6, 3, 'rub', now());


Есть идеи?
  • Вопрос задан
  • 131 просмотр
Решения вопроса 1
Только уже указанный вариант с подзапросом возможен, так как нет возможности использовать группировку и не участвующие в группировке или неаггрегированные поля. Единственное что, выгоднее будет использовать первичный ключ для JOIN
SELECT n.* FROM course n
JOIN (SELECT MAX(created_at) created_at FROM course GROUP BY currency) m
USING(created_at)


Одним запросом, судя по explain, значительно дороже будет такой запрос
SELECT n.* FROM course n
LEFT JOIN course m
ON n.currency = m.currency AND n.created_at < m.created_at
WHERE m.id IS NULL
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@MaximaXXl
Это больше на изврат похоже, условие без подзапросов ...
но вот:
select distinct
FIRST_VALUE(currency) OVER (PARTITION BY currency ORDER BY created_at desc) currency,
FIRST_VALUE(price)    OVER (PARTITION BY currency ORDER BY created_at desc) price
       from course

Данных нет, не проверял, но должно работать
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
26 мая 2020, в 02:01
4500 руб./за проект
26 мая 2020, в 00:42
10000 руб./за проект
25 мая 2020, в 22:16
3000 руб./за проект