COUNT(*) OVER (PARTITION BY ...)窗口函数——在每一行上执行聚合操作

它用于在查询结果中执行聚合操作,而不会影响查询的分组行数,同时在每个分组内进行计数。

  • COUNT(): 这表示要计算在窗口内的行数, 代表计算所有行。
  • OVER: 这引入了窗口函数的定义,它告诉数据库引擎在什么样的窗口内执行计数。
  • (PARTITION BY …): 这部分定义了窗口的分区方式,即如何将数据划分为不同的分组。PARTITION BY
    子句指定一个或多个列,根据这些列的值将数据划分为不同的窗口。

看个问题

编写一个 SQL 语句,将某个员工与具有相同许可证的所有其他员工进行匹配。
在这里插入图片描述
输出的结果为:
在这里插入图片描述

  • 员工 ID 1001 和 2002 将在预期输出中,因为它们都带有 A 类、B 类和C 类许可证。
  • 员工 ID 4004 和 5005 将在预期输出中,因为它们都带有 A 类、B 类和 D类许可证。
  • 尽管员工 ID 3003 与员工 ID 4004 和 5005 具有相同的许可证,但这些员工 ID没有与 3003 相同的许可证。

表和数据

DROP TABLE IF EXISTS #Employees;
GO

CREATE TABLE #Employees
(
EmployeeID  INTEGER,
License     VARCHAR(100),
PRIMARY KEY (EmployeeID, License)
);
GO

INSERT INTO #Employees (EmployeeID, License) VALUES
(1001,'Class A'),(1001,'Class B'),(1001,'Class C'),
(2002,'Class A'),(2002,'Class B'),(2002,'Class C'),
(3003,'Class A'),(3003,'Class D'),
(4004,'Class A'),(4004,'Class B'),(4004,'Class D'),
(5005,'Class A'),(5005,'Class B'),(5005,'Class D');
GO

咋写?

1.要全部都匹配上
2.要计算出数量

如果直接用自己关联(#Employees A inner join #Employees B
on A.License=B.License and A.EmployeeID<>B.EmployeeID
group by A.EmployeeID,B.EmployeeID)就是只计算匹配上的个数,没有都匹配上,且没匹配总数量,那要怎么既单个都匹配上且总数也对的上呢?有什么函数是可以显示单个和总数的之间的关系?
就要用到COUNT(*) OVER (PARTITION BY …)窗口函数
每行都显示出匹配上的总数,这样就不用再group by算一遍总数再匹配,省了很多的时间。
在这里插入图片描述

结果

WITH cte_Count as--为了匹配许可证数量
(
SELECT  EmployeeID,
        COUNT(*) AS LicenseCount
FROM    #Employees
GROUP BY EmployeeID
),
cte_CountWindow as--为了获取许可证数量
(
SELECT  a.EmployeeID AS EmployeeID_A,
        b.EmployeeID AS EmployeeID_B,
        COUNT(*) OVER (PARTITION BY a.EmployeeID, b.EmployeeID) AS CountWindow
FROM    #Employees a CROSS JOIN
        #Employees b
WHERE   a.EmployeeID <> b.EmployeeID and a.License = b.License
)
SELECT  DISTINCT
        a.EmployeeID_A,
        a.EmployeeID_B,
        a.CountWindow AS LicenseCount
FROM    cte_CountWindow a 
	    inner join cte_Count b ON a.CountWindow = b.LicenseCount --总数量匹配上
								  and a.EmployeeID_A = b.EmployeeID --人
		inner join cte_Count c ON a.CountWindow = c.LicenseCount 
								  and a.EmployeeID_B = c.EmployeeID;

COUNT(*) OVER (PARTITION BY …)显示了分组后的每行数据与总的数据的关系,利用这个关系,可以匹配上总数一致。

应用场景

COUNT(*) OVER (PARTITION BY …) 通常应用于窗口函数中,用于分析和报告需要在结果集中的每行上执行聚合操作的场景。以下是一些常见的应用场景:

  • 计算每组的行数:窗口函数允许你在结果集中的每一行上计算分组内的行数,而不需要使用 GROUP BY子句。这对于需要在保持所有行的情况下查看每个分组的大小的情况非常有用。
  • 计算累积和或平均值:你可以使用窗口函数来计算每一行的累积和、平均值或其他聚合指标,而不必创建中间结果或更改结果集的结构。
  • 识别排名和百分比:窗口函数允许你为每一行计算排名或百分比,例如,找出每个销售员的销售额在总销售额中的百分比。
  • 查找首次出现或最后出现的事件:你可以使用窗口函数来确定每组内首次或最后一次出现某个事件的时间戳或行。
  • 分析前后行:你可以使用窗口函数来分析前一行和后一行的数据,例如,计算每个时间点的收益与前一个时间点的差异。
  • 分组内数据分布分析:窗口函数可用于查找每组内数据的分布情况,如查找每组内的最大、最小值,或者计算分位数。
  • 复杂的累积计算:在某些情况下,你可能需要执行复杂的累积计算,包括多次计算和分组。窗口函数可以帮助你处理这些需求,而不必使用复杂的子查询或连接。

总之,窗口函数允许你在结果集的每一行上执行聚合操作,而不会减少结果集的行数,从而提供了更灵活和强大的数据分析工具。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值