我正在分析一些在Count()竞赛中利用空OVER子句的代码。
示例:
SELECT
ROW_NUMBER() OVER (ORDER BY Priority DESC) AS RowID,
CAST((COUNT(*) OVER() / @pagesize) AS Int) AS TotalPages,
我试图理解为什么在这里使用空的OVER子句。
在我上面列出的这两行之下还有其他标准选择元素,当我从第二行TotalPages行中删除空的OVER子句时,我得到如下错误:
Column 'TableA.Priority' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
一旦我把OVER()放回去,错误就消失了。
我对OVER子句的理解非常有限......我觉得我理解RowID行中发生了什么......但TotalPages行让我感到困惑。
答案 0 :(得分:8)
OVER()是分析函数的一部分,用于定义记录集中的分区。 OVER()只是一个分区并应用于整个数据集
即。 COUNT(*)OVER()将在每行中返回数据集中的记录数。
答案 1 :(得分:1)
说我们的表是employees
:
+-----------+-------+---------+
| badge_num | name | surname |
+-----------+-------+---------+
| 1 | John | Smith |
| 2 | Mark | Pence |
| 3 | Steve | Smith |
| 4 | Bob | Smith |
+-----------+-------+---------+
运行
SELECT surname, COUNT(*)
FROM employees
GROUP BY surname;
我们将得到:
+---------+----------+
| surname | COUNT(*) |
+---------+----------+
| Smith | 3 |
| Pence | 1 |
+---------+----------+
正在运行
SELECT surname, COUNT(*) OVER()
FROM employees
GROUP BY surname;
我们将得到:
+---------+-----------------+
| surname | COUNT(*) OVER() |
+---------+-----------------+
| Smith | 2 |
| Pence | 2 |
+---------+-----------------+
在第二种情况下,我们仅在每一行中计算整个select(而不是单个分区)的行数。
答案 2 :(得分:0)
总而言之,OVER子句可以与排名函数(Rank,Row_Number,Dense_Rank ..),聚合函数(AVG,Max,Min,SUM ...等)以及分析函数(First_Value,Last_Value)一起使用,以及其他几个)。
让我们看看OVER子句的基本语法
OVER (
[ <PARTITION BY clause> ]
[ <ORDER BY clause> ]
[ <ROW or RANGE clause> ]
)
根据: 它用于对数据进行分区并在具有相同数据的组上执行操作。
订购者: 它用于定义分区中数据的逻辑顺序。如果不指定分区,则整个结果集将被视为单个分区
: 可以用来指定执行该操作时应该在分区中考虑哪些行。
让我们举个例子:
这是我的数据集:
Id Name Gender Salary
----------- -------------------------------------------------- ---------- -----------
1 Mark Male 5000
2 John Male 4500
3 Pavan Male 5000
4 Pam Female 5500
5 Sara Female 4000
6 Aradhya Female 3500
7 Tom Male 5500
8 Mary Female 5000
9 Ben Male 6500
10 Jodi Female 7000
11 Tom Male 5500
12 Ron Male 5000
所以让我执行不同的场景,看看数据如何受到影响,我将从困难的语法变成简单的语法
Select *,SUM(salary) Over(order by salary RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as sum_sal from employees
Id Name Gender Salary sum_sal
----------- -------------------------------------------------- ---------- ----------- -----------
6 Aradhya Female 3500 3500
5 Sara Female 4000 7500
2 John Male 4500 12000
3 Pavan Male 5000 32000
1 Mark Male 5000 32000
8 Mary Female 5000 32000
12 Ron Male 5000 32000
11 Tom Male 5500 48500
7 Tom Male 5500 48500
4 Pam Female 5500 48500
9 Ben Male 6500 55000
10 Jodi Female 7000 62000
只需观察sum_sal部分。在这里,我使用的是按薪水排序,并使用“无限制的前导和当前行之间的范围” 。 在这种情况下,我们不使用分区,因此整个数据将被视为一个分区,并且我们按薪水排序。 这里重要的是未绑定的前行和当前行。这意味着当我们计算总和时,从每一行的开始行到当前行。 但是,如果我们看到薪水为5000且名称为“ Pavan”的行,则理想情况下应为17000,薪水为5000且名称为Mark的行应为22000。但是由于我们使用的是 RANGE 在这种情况下,如果找到任何相似的元素,则将它们视为相同的逻辑组并对它们执行操作,并为该组中的每个项目分配值。这就是为什么我们对薪金= 5000具有相同的值的原因。引擎将薪金提高到5000 = Name = Ron并计算总和,然后将其分配给所有薪金= 5000。
Select *,SUM(salary) Over(order by salary ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as sum_sal from employees
Id Name Gender Salary sum_sal
----------- -------------------------------------------------- ---------- ----------- -----------
6 Aradhya Female 3500 3500
5 Sara Female 4000 7500
2 John Male 4500 12000
3 Pavan Male 5000 17000
1 Mark Male 5000 22000
8 Mary Female 5000 27000
12 Ron Male 5000 32000
11 Tom Male 5500 37500
7 Tom Male 5500 43000
4 Pam Female 5500 48500
9 Ben Male 6500 55000
10 Jodi Female 7000 62000
因此,对于无界前导行和当前行之间的行,区别在于相同值的项目而不是将它们分组在一起,它计算从开始行到当前行的SUM,并且不处理相同行的项目值与 RANGE
不同Select *,SUM(salary) Over(order by salary) as sum_sal from employees
Id Name Gender Salary sum_sal
----------- -------------------------------------------------- ---------- ----------- -----------
6 Aradhya Female 3500 3500
5 Sara Female 4000 7500
2 John Male 4500 12000
3 Pavan Male 5000 32000
1 Mark Male 5000 32000
8 Mary Female 5000 32000
12 Ron Male 5000 32000
11 Tom Male 5500 48500
7 Tom Male 5500 48500
4 Pam Female 5500 48500
9 Ben Male 6500 55000
10 Jodi Female 7000 62000
这些结果与
相同Select *, SUM(salary) Over(order by salary RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as sum_sal from employees
这是因为超额(按薪水排序)只是超额(按薪水排序)的无限制限制,当前行之间的距离 因此,无论我们在什么地方简单地指定排序依据而没有 ROWS或RANGE ,它都将未绑定先行和当前行之间的范围作为默认值。
注意:这仅适用于实际接受RANGE / ROW的函数。例如,ROW_NUMBER和其他一些人不接受RANGE / ROW,在这种情况下,这不会出现在图片中。
到目前为止,我们看到带有子句的Over子句采用了Range / ROWS,语法看起来像这样 UNBOUNDED PRECEDING和CURRENT ROW之间的范围 它实际上是从第一行开始计算到当前行。但是,如果要计算整个数据分区的值并为每一列(从第一行到最后一行)使用它,该怎么办。这是该查询
Select *,sum(salary) Over(order by salary ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as sum_sal from employees
Id Name Gender Salary sum_sal
----------- -------------------------------------------------- ---------- ----------- -----------
1 Mark Male 5000 62000
2 John Male 4500 62000
3 Pavan Male 5000 62000
4 Pam Female 5500 62000
5 Sara Female 4000 62000
6 Aradhya Female 3500 62000
7 Tom Male 5500 62000
8 Mary Female 5000 62000
9 Ben Male 6500 62000
10 Jodi Female 7000 62000
11 Tom Male 5500 62000
12 Ron Male 5000 62000
我指定的是 UNBOUNDED FOLLOWING ,而不是CURRENT ROW,它指示引擎计算直到每一行的分区的最后一条记录。
现在您想知道什么是带有空花括号的OVER()?
这只是超额付款的捷径(按无约束的前提和无约束的跟随之间的工资行排序)
此处我们间接指定将所有结果集视为一个分区,然后从每个分区的第一条记录到最后一条记录进行计算。
Select *,Sum(salary) Over() as sum_sal from employees
Id Name Gender Salary sum_sal
----------- -------------------------------------------------- ---------- ----------- -----------
1 Mark Male 5000 62000
2 John Male 4500 62000
3 Pavan Male 5000 62000
4 Pam Female 5500 62000
5 Sara Female 4000 62000
6 Aradhya Female 3500 62000
7 Tom Male 5500 62000
8 Mary Female 5000 62000
9 Ben Male 6500 62000
10 Jodi Female 7000 62000
11 Tom Male 5500 62000
12 Ron Male 5000 62000
我确实为此制作了一个视频,如果您有兴趣可以访问它。 https://www.youtube.com/watch?v=CvVenuVUqto&t=1177s
谢谢, 帕万·库玛(Pavan Kumar Aryasomayajulu) HTTP://xyzcoder.github.io