#vertica
Вопрос:
Следующий vertica
пример из https://www.vertica.com/docs/11.0.x/HTML/Content/Authoring/AnalyzingData/SQLAnalytics/AnalyticFunctionsVersusAggregateFunctions.htm?tocpath=Analyzing Data|SQL Analytics|_____2
CREATE TABLE employees(emp_no INT, dept_no INT);
INSERT INTO employees VALUES(1, 10);
INSERT INTO employees VALUES(2, 30);
INSERT INTO employees VALUES(3, 30);
INSERT INTO employees VALUES(4, 10);
INSERT INTO employees VALUES(5, 30);
INSERT INTO employees VALUES(6, 20);
INSERT INTO employees VALUES(7, 20);
INSERT INTO employees VALUES(8, 20);
INSERT INTO employees VALUES(9, 20);
INSERT INTO employees VALUES(10, 20);
INSERT INTO employees VALUES(11, 20);
COMMIT;
Если я выполняю этот запрос без order by
, я получаю одинаковое значение счетчика для всех строк
dbadmin@b006bc38a718(*)=>
select
emp_no
, dept_not
, count(*) over (partition by dept_not) as emp_count
from employees;
emp_no | dept_not | emp_count
-------- ---------- -----------
6 | 20 | 6
7 | 20 | 6
8 | 20 | 6
9 | 20 | 6
10 | 20 | 6
11 | 20 | 6
1 | 10 | 2
4 | 10 | 2
2 | 30 | 3
3 | 30 | 3
5 | 30 | 3
(11 rows)
Но если я добавлю order by
, то получу добавочную стоимость
dbadmin@b006bc38a718(*)=>
select
emp_no
, dept_not
, count(*) over (partition by dept_not order by emp_no) as emp_count
from employees;
emp_no | dept_not | emp_count
-------- ---------- -----------
2 | 30 | 1
3 | 30 | 2
5 | 30 | 3
1 | 10 | 1
4 | 10 | 2
6 | 20 | 1
7 | 20 | 2
8 | 20 | 3
9 | 20 | 4
10 | 20 | 5
11 | 20 | 6
(11 rows)
Time: First fetch (11 rows): 85.075 ms. All rows formatted: 85.139 ms
На что это влияет order by
? Почему я получаю добавочное значение?
Ответ №1:
Если предложение window содержит только PARTITION BY
, оно возвращает общую сумму раздела — для каждой строки раздела одно и то же значение.
Если предложение window содержит оба PARTITION BY
и ORDER BY
, оно возвращает количество выполняемых операций в разделе . Итак, используя ORDER BY
выражение, сколько строк было подсчитано до сих пор в разделе.
Именно так работают оконные функции. Они дают вам целый мир возможностей…
Комментарии:
1. ОК. хотя может быть полезно предоставить способ подсчета количества выполняемых операций, я чувствую, что использование фразы
order by
— не лучший вариант и вызывает путаницу. Кажется, что количество выполняемых операций является побочным эффектомorder by
2. и
partition by
, похоже, такие же, какgroup by
. Интересно, почему бы не использовать фразуgroup by
, а неpartition by
потомуpartition
, что имеет другое значение в Vertica.3. Да, Manu — но если вы перейдете
SUM(amount) OVER(PARTITION BY iso_ctry ORDER BY sales_dt)
, вы получите текущую сумму ваших продаж по стране с течением времени. И это действительно удобно…4. GROUP BY возвращает одну строку на
GROUP BY
комбинацию списка столбцов, уменьшая количество строк.PARTITION BY
возвращает все входные строки, но может возвращать один и тот же результат для всех строк в разделе. Это два очень разных варианта использования.5. правильно ли я понимаю, что использую аналитическую функцию вместо агрегатной функции, если мне нужно выходное значение для каждой входной строки?
Ответ №2:
Это происходит потому, что Vertica применяет значение по умолчанию frame-clause
, которое определяется как:
RANGE UNBOUNDED PRECEDING AND CURRENT ROW
Итак, чтобы получить желаемый результат, вы можете добавить предложение frame, как показано ниже, после вас ORDER BY
в OVER()
предложении:
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
Это поведение задокументировано как:
Если в предложении OVER не указывается рамка окна, функция создает окно по умолчанию, которое простирается от текущей строки до первой строки в текущем разделе.