SQL - 何时使用空的OVER子句?

时间:2010-07-28 16:41:02

标签: sql sql-server-2005 sql-server-2008

我正在分析一些在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行让我感到困惑。

3 个答案:

答案 0 :(得分:8)

OVER()是分析函数的一部分,用于定义记录集中的分区。 OVER()只是一个分区并应用于整个数据集

即。 COUNT(*)OVER()将在每行中返回数据集中的记录数。

请查看此http://msdn.microsoft.com/en-us/library/ms189461.aspx

答案 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