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

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的值了吗?确实高明。感叹自己过去怎么就没想到呢?还是很开心可以知道这个办法的。

时间: 2024-10-21 05:13:28

SQL Server ->> 间接实现COUNT(DISTINCT XXX) OVER(PARTITION BY YYY ORDER BY ZZZ)的相关文章

SQL Server "Login failed for user 'xxx\yyy'. [SQLSTATE 28000] (Error 18456). " 问题解决

问题:SQL Server 2014,使用Job定时从Linked Server同步数据,执行时报"Login failed for user '域帐号'. [SQLSTATE 28000] (Error 18456). " 解决:通过配置管理工具修改SQL Server Agent服务启动帐号为域帐号,参见: Login failed for [SQLSTATE 28000] (Error 18456) the step failed SQL Server "Login f

sql server 2005中的分区函数用法(partition by 字段)

分组取TOP数据是T-SQL中的常用查询, 如学生信息管理系统中取出每个学科前3名的学生.这种查询在SQL Server 2005之前,写起来很繁琐,需要用到临时表关联查询才能取到.SQL Server 2005后之后,引入了row_number()函数,row_number()函数的分组排序功能使这种操作变得非常简单. create database StudentDBgo use StudentDBgo create table Student  --学生成绩表( id int,  --主键

Sql server 表表达式

1.表表达式概述 (1)表表达式(table expression) 是一个命名的查询表达式.代表一个有效的关系表 (2)在DML 中,使用表表达式和使用其他表非常类似 (3)sqlserver 支持4种表表达式: 派生表.公用表达式(CTE).视图 .内嵌值函数(内嵌TVF) (4)表表达式没有任何的物理实例化.是虚拟的.内部查询是嵌套 的 (5)使用表表达式的好处是代码逻辑方便有关.与性能无关.表表达式本身不会对性能带来正负影响 2.有效定义表表达式查询需要满足的3个要求 2.1 无法保证顺

数据库开发基础-SQl Server 聚合函数、数学函数、字符串函数、时间日期函数

SQL 拥有很多可用于计数和计算的内建函数. 函数的语法 内建 SQL 函数的语法是: SELECT function(列) FROM 表 函数的类型 在 SQL 中,基本的函数类型和种类有若干种.函数的基本类型是: Aggregate 函数 Scalar 函数 合计函数(Aggregate functions) Aggregate 函数的操作面向一系列的值,并返回一个单一的值. 注释:如果在 SELECT 语句的项目列表中的众多其它表达式中使用 SELECT 语句,则这个 SELECT 必须使

sql server触发器实现插入时操作另一张表

以前都是也得mysql,现在写sqlserver的触发器,感觉改动还是蛮大的 1.定义变量 #在mysql中变量直接这么定义就可以了 SET @VALUE = "111"; #在sql server中 declare @count int; #并赋值 set @count =0; #如果是查询,必须这么些 select @count = count(*) from WQ_MNINF_D_REAL where [email protected]; 2.判断 在mysql中,if判断的格式

SQL SERVER技术内幕之6 集合查询

1.定义 集合运算会对两个输入查询的结果集进行逐行比较,根据比较结果和所使用的集合运算来确定某一行是否应该包含在集合运算的结果中.因为集合运算是针对集合之间进行的计算,所以集合运算涉及的两个查询不能包含Order By子句.包含Order By子句的查询可以确保结果的排列顺序,因此,这样的查询返回的不是集合,而是游标. ANSI SQL对每种集合运算都支持两个选项:DISTINCT(默认值)和ALL,DISTINCT逻辑上可以从两个输入的多集中消除重复的行,然后返回一个集合.ALL对两个多集进行

SQL Server遗失管理权限账号密码怎么办?

原文:SQL Server遗失管理权限账号密码怎么办? 假如一个SQL Server实例只允许"SQL身份认证"模式登录数据库,而糟糕的是你忘记了sa的密码(sa出于安全考虑应该被禁用,这里仅仅为了描述问题)或其它具有sysadmin角色的登录名的密码?个人就遇到这样一个案例,HK一同事在一台测试服务器安装了一个测试用途的SQL Server数据库,然后这个同事离职前没有交接这个测试服务器任何信息.那现在就麻烦了.我没有任何权限,我如何获取sysadmin的权限呢?或者还有比较多的场景

SQL SERVER的一些操作

最近忙着折腾一些项目,要用到一些数据库,主要在Oracle ,mysql,sqlserver 和 sqlite 这四类数据库来回折腾,指令常弄混,还是记下来好 ! SQL server 的操作: 在CMD窗口下,直接输入sqlcmd,即可使用控制台操作: 登陆数据库 sqlcmd -S 数据库服务器地址 -U 用户名 -P 密码 或 sqlcmd -S 数据库服务器地址\数据库实例名 -U 用户名 -P 密码 查询数据库 查看有哪些数据库 >1 SELECT name FROM sys.data

MySQL、Oracle和SQL Server的分页查询语句

原文地址:http://www.cnblogs.com/ginponson/p/5746435.html 假设当前是第PageNo页,每页有PageSize条记录,现在分别用Mysql.Oracle和SQL Server分页查询student表. 1.Mysql的分页查询 SELECT * FROM student LIMIT (PageNo - 1) * PageSize,PageSize; 理解:(Limit n,m)  =>从第n行开始取m条记录,n从0开始算. 2.Oracel的分页查询