#mysql #sql #window-functions
#mysql #sql #оконные функции
Вопрос:
Я заметил из следующих двух оконных функций:
WITH sales AS (
select 2020 as year, 100 as revenue UNION
select 2021 as year, 200 as revenue UNION
select 2022 as year, 300 as revenue UNION
select 2023 as year, 100 as revenue
)
SELECT JSON_ARRAYAGG(revenue) OVER (order by year) FROM sales LIMIT 1;
# revenue_list
[100]
И это:
WITH sales AS (
select 2020 as year, 100 as revenue UNION
select 2021 as year, 200 as revenue UNION
select 2022 as year, 300 as revenue UNION
select 2023 as year, 100 as revenue
)
SELECT JSON_ARRAYAGG(revenue) OVER () revenue_list FROM sales LIMIT 1;
# revenue_list
[100, 200, 300, 100]
Похоже, что поведение фрейма по умолчанию:
- Если ничего не указано —
()
— тогда фрейм по умолчаниюUNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
- Если что-то указано —
(order by year)
или(partition by year)
и т. Д. — Тогда фрейм по умолчаниюUNBOUNDED PRECEDING AND CURRENT ROW
.
Это правильное понимание поведения фрейма по умолчанию? Если да, то почему был сделан этот выбор? (Например, почему бы просто не иметь его всегда неограниченным, если не указано пользователем?)
Ответ №1:
LIMIT 1
Предложение в первом запросе вводит вас в заблуждение. Рассмотрим полный запрос без какого-либо LIMIT
предложения:
SELECT JSON_ARRAYAGG(revenue) OVER (ORDER BY year) FROM sales;
Результирующий набор, созданный на основе этого:
Причина, по которой [100]
returned…is совершенно произвольно. У вас нет ORDER BY
предложения с вашим LIMIT
запросом, поэтому «первая» запись, которую мы видим в результирующем наборе, просто возвращается (но теоретически это может быть любая из четырех записей).
OVER ()
Версия просто отобразит всю таблицу, объединенную в массив JSON, но будет отображать это значение для каждой записи.
SELECT JSON_ARRAYAGG(revenue) OVER () FROM sales; -- [100, 200, 300, 100] each record
SELECT JSON_ARRAYAGG(revenue) FROM sales; -- [100, 200, 300, 100] one record
Комментарии:
1. другими словами, фрейм по умолчанию всегда
UNBOUNDED PRECEDING AND CURRENT ROW
?2. Да, правильно. So
OVER (ORDER BY year)
идентиченOVER (ORDER BY year ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
… но обычно мы всегда используем первое для краткости.