Почему это поведение по умолчанию OVER () для фрейма?

#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) … но обычно мы всегда используем первое для краткости.