SQL Server ->> 间接实现COUNT(DISTINCT XXX) OVER(PARTITION BY YYY)

SQL Server 2005版本开始支持了窗口函数(Windowing Function)和OVER字句。SQL Server 2012版本开始支持了窗口函数的ORDER BY字句实现连续/累计聚合功能。但是有个功能到SQL Server 2014版本为止(从目前SQL Server 2016 CTP3来看,还是不支持),就是COUNT(DISTINCT XXX) OVER(PARTITION BY YYY ORDER BY ZZZ)。

一直觉得这个事情没有办法用比较巧妙地办法做到,只能是用CROSS APPLY或者循环去把数据集“UNION ALL”起来。今天在Google上找到了一个别人想到的办法,顿时觉得自己怎么那么笨,没有想到这个办法呢。巧妙之处在于用一个带有DENSE_RANK函数的子查询配合MAX函数实现。下面是测试代码:

 

CREATE TABLE Foo (
fookey INT PRIMARY KEY,
company VARCHAR(30),
sales_rep VARCHAR(30),
client VARCHAR(30));

INSERT INTO Foo VALUES(1, 'ABC Corp.', 'Joe', 'Client1');
INSERT INTO Foo VALUES(2, 'ABC Corp.', 'Joe', 'Client2');
INSERT INTO Foo VALUES(6, 'ABC Corp.', 'Joe', 'Client2');
INSERT INTO Foo VALUES(3, 'ABC Corp.', 'Peter', 'Client2');
INSERT INTO Foo VALUES(4, 'DEF Corp.', 'Joe', 'Client1');
INSERT INTO Foo VALUES(5, 'DEF Corp.', 'Joe', 'Client3');

SELECT DISTINCT company, sales_rep, client,
MAX(rk1) OVER(PARTITION BY sales_rep) AS rep_distinct_client_cnt,
MAX(rk2) OVER(PARTITION BY company) AS company_distinct_client_cnt
FROM (
SELECT fookey, company, sales_rep, client,
DENSE_RANK() OVER(PARTITION BY sales_rep ORDER BY client) As rk1,
DENSE_RANK() OVER(PARTITION BY company ORDER BY client) As rk2
FROM Foo) AS F;

 

这个办法精妙的地方便是利用了DENSE_RANK本身会对相同值返回相同的排序号的特点,这点恰恰符合了我们需要DISTINCT的作用。其次,排序号和COUNT的相同之处不就是对记录的个数统计吗?那么取得最大的排序号不就相当于拿到了COUNT的值了吗?确实高明。感叹自己过去怎么就没想到呢?还是很开心可以知道这个办法的。

你可能感兴趣的:(SQL Server ->> 间接实现COUNT(DISTINCT XXX) OVER(PARTITION BY YYY))