SQLServer 之 Group By 和 Compute By
创建测试表,如下:
CREATE TABLE tableTest
(
Id INT PRIMARY KEY,
DepartMent NVARCHAR(30),
Name NVARCHAR(30),
Salary int
)
添加测试数据,如下图:
一、GROUP BY
规则1:单值规则,跟在SELECT后面的列表,对于每个分组来说,必须返回且仅仅返回一个值。
在select指定的字段要么就要包含在Group By语句的后面,作为分组的依据;要么就要被包含在聚合函数中。
SELECT DepartMent, COUNT(1) Num
FROM tableTest
GROUP BY DepartMent
因此,当希望查询出不是分组依据,且不包含在聚合函数中的字段信息时,要另寻解决方案。
例如:查询每个部门,最高工资的那个人的姓名,部门,工资。
方案1:关联子查询
SELECT DepartMent,Name,Salary
FROM tableTest T1
WHERE NOT EXISTS(SELECT DepartMent,Name,Salary
FROM tableTest T2
WHERE T2.DepartMent = T1.DepartMent
AND T2.Salary > T1.Salary
)
完全符合要求。对于上面的关联子查询,解释:遍历工资表的所有记录,查找不存在比当前记录部门相同且工资还大的记录。
虽然,关联子查询的语法非常简单,但是性能并不好。因为对于每一条记录,都要执行一次子查询。
方案2:衍生表
使用衍生表的思路是,先执行一个子查询,得到一个临时结果集,然后用临时结果集和原表进行INNER JOIN操作。就能得到最高工资的人的信息。
SELECT T1.DepartMent,T1.Name,T1.Salary
FROM tableTest T1 INNER JOIN
( SELECT DepartMent,MAX(Salary) maxSalary FROM tableTest GROUP BY DepartMent ) T2
ON T1.DepartMent = T2.DepartMent AND T1.Salary = T2.maxSalary
衍生表的方式性能优于关联子查询,因为衍生表的方式只执行了一次子查询。但是它需要一张临时表来存储临时记录。因此,这个方案也并不是最佳的解决方案。
方案3:使用LEFT JOIN + IS NULL
这是一个更妙的解决方案,当我们用一个外联结去匹配记录时,当匹配的记录不存在,就会用NULL来代替相应的列。
先看如下 SQL 语句:
SELECT T1.Id,T1.DepartMent,T1.Name,T1.Salary,T2.Id,T2.DepartMent,T2.Name,T2.Salary
FROM tableTest T1 LEFT JOIN tableTest T2
ON T1.DepartMent = T2.DepartMent AND T1.Salary < T2.Salary
从中你看出,当T2表中,不存在比T1表中工资高的记录时就返回NULL。
由此,加一个IS NULL条件即可。
SELECT T1.DepartMent,T1.Name,T1.Salary
FROM tableTest T1 LEFT JOIN tableTest T2
ON T1.DepartMent = T2.DepartMent AND T1.Salary < T2.Salary
WHERE T2.Id IS NULL
JOIN解决方案适用于针对大量数据查询并且可伸缩比较时。它总是能比基于子查询的解决方案更好地适应数据量的变量。
方案4:对额外的列使用聚合函数(不适合同是有多条数据满足条件的情况)
GROUP BY 时,SELECT列表必须返回的是单值,那么我们可以通过使用聚合函数,让这个列返回单值。
SELECT DepartMent,MAX(Name),MAX(Salary)
FROM tableTest
GROUP BY DepartMent
其实,返回的数据是有问题的,当工资相同时,它就返回按姓名从大到小排列的第一个姓名。也就是说,当工资相同时,它只能够返回一条记录。
方案5:Row_Number() OVER(PARTITION BY partField ORDER BY orderField)
WITH tableB AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY DepartMent ORDER BY Salary DESC) AS part ,DepartMent, Name, Salary
FROM tableTest
)
SELECT * FROM tableB WHERE part=1
输出如下:
二、Compute 和 Compute By
GROUP BY子句有个缺点,就是返回的结果集中只有合计数据,而没有原始的详细记录。如果想在SQL SERVER中完成这项工作,可以使用COMPUTE BY子句。COMPTE生成合计作为附加的汇总列出现在结果集的最后。当与BY一起使用时,COMPUTE 子句在结果集内生成控制中断和分类汇总。
下列 SELECT 语句使用简单 COMPUTE 子句生成 tableTest表中 Salary 的求和总计:
SELECT Department, Name, Salary
FROM tableTest
COMPUTE SUM(Salary)
下列查询在 COMPUTE 子句中加入可选的 BY 关键字,以生成每个组的小计:
SELECT Department, Name, Salary
FROM tableTest
ORDER BY Department
COMPUTE SUM(Salary) BY Department
SELECT 语句的结果用4 个结果集返回,2个组中的每个组都有两个结果集。每个组的第一个结果集是一个行集,其中包含选择列表中所请求的信息。每个组的第二个结果集包含 COMPUTE 子句中两个 SUM 函数的小计。
COMPUTE BY 子句的规则:
(1)不能将distinct与行统计函数一起使用
(2)compute ??? by 子句中 ???出的列必须出现在选择列表中
(3)不能在含有compute by 子句的语句中使用select into 子句,因为包括compute 子句的语句会产生不规则的行。
(4)如果使用了compute by子句,则必须使用order by 子句, 而且compute by子句中的列必须包含在order by 子句中,并且对列的前后顺序和起始项都要一致(即compute by子句中的列必须是order by子句中列表的全部,或者前边的连续几个)。
(5)如果compute 省略了 by ,则order by 也可以省略
(6)如果compute by 子句包含多列时,会将一个组(第一个列分的组)分成若干个子组(利用后面的列),并对每层子组进行统计。
(7)使用多个compute by子句时,会分别按不同的组统计出结果。详细信息还是按照正常的第一个分组方式显示。
(8)compute by 子句中可以使用多个统计函数,他们互不影响
(9)compute by 子句中可以不包含by ,而只用compute 此时不对前面信息分组,而只对全部信息进行统计。
在实际开发中compute与compute by的作用并不是很大,SQL Server支持compute和compute by,而Access并不支持。
在 COMPUTE 或 COMPUTE BY 子句中,不能包含 ntext、text 或 image 数据类型。
三、 COMPUTE 和 GROUP BY 区别
GROUP BY 生成单个结果集。每个组都有一个只包含分组依据列和显示该组子聚合的聚合函数的行。选择列表只能包含分组依据列和聚合函数。
COMPUTE 生成多个结果集。一类结果集包含每个组的明细行,其中包含选择列表中的表达式。另一类结果集包含组的子聚合,或 SELECT 语句
的总聚合。选择列表可包含除分组依据列或聚合函数之外的其它表达式。聚合函数在 COMPUTE 子句中指定,而不是在选择列表中。
SQLServer 之 Group By 和 Compute By的更多相关文章
- 【转载】Sqlserver使用Group By进行分组并计算每个组的数量
在SQL语句查询中,Group By语句时常用来进行分组操作,有时候在分组的同时还需要计算出每个组的数量多少.在Sqlserver数据库中可以使用Group By加Count聚合函数来实现此功能,即通 ...
- 【SQL】SqlServer中Group By后,字符串合并
参考: 1.SQL查询语句 group by后, 字符串合并 2.sql for xml path用法 #需求: 合并列值 表结构,数据如下: id value ----- ------ aa bb ...
- sqlserver之group by 与over函数
group by 函数主要用来对数据进行分组,over()函数则是一个“开窗函数”,它更多的是与聚合函数如:sum().max().min().avg().count()等函数以及排名函数如:row_ ...
- sqlserver 分组 group by
select 名称, COUNT(名称) as 数量之和from 信息group by all 名称
- SQLServer之GROUP BY语句
GROUP BY 语句 GROUP BY 语句用于结合合计函数,根据一个或多个列对结果集进行分组. SQL GROUP BY 语法 SELECT column_name, aggregate_func ...
- 分享一下我研究SQLSERVER以来收集的笔记
分享一下我研究SQLSERVER以来收集的笔记 前言 为什麽分享??因为像现在网上很多人攻城师那样,转行去卖水果,卖早餐,总有一日我也会离开这个行业的 由于本人不是在大公司上班工资很低,我希望有一天存 ...
- Compute Shader
[Compute Shader] 1.Similar to regular shaders, compute shaders are Asset files in your project, with ...
- sqlserver backup and restore -- partital restore
Like a tratitional database, sqlserver not only could resotre full database but also do restore one ...
- SQL 笔记 By 华仔
-------------------------------------读书笔记------------------------------- 笔记1-徐 最常用的几种备份方法 笔记2-徐 收缩数据 ...
随机推荐
- 【SQL】176. Second Highest Salary
Write a SQL query to get the second highest salary from the Employee table. +----+--------+ | Id | S ...
- Linux内核镜像格式
<Linux内核镜像格式> Linux内核有多种格式的镜像,包括vmlinux.Image.zImage.bzImage.uImage.xipImage.bootpImage等. ➤k ...
- FastReport.Net使用:[36]"续表"
1. RepeatedBand的打印和子报表的使用. RepeatedBand实现方法:设置Band为每页重复.注意,从第二次打印开始,就是重复打印了.第一次打印不认为是RepeatedBand. 报 ...
- 网络流—最大流(Edmond-Karp算法)
一.含义 从源点到经过的所有路径的最终到达汇点的所有流量和 例如: 在这个图中求源点1,到汇点4的最大流.答案为50,其中1->2->4为20 :1->4为20 :1->2-& ...
- HDU 2157 How many ways?? (邻接矩阵快速幂)
http://acm.hdu.edu.cn/showproblem.php?pid=2157 题意 : 给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值 从这道题 ...
- [GCJ2017R2]Fresh Chocolate
题目大意: 有n个团和很多盒糖,每个团中人数不一定相同,每盒糖中都有p颗糖. 现在要给每个团发糖,要求每个人都要发到糖,只有一盒糖发完后才能发下一盒糖. 发糖的顺序可以任意安排,问经过合理安排后,最多 ...
- Miller-Rabin算法 codevs 1702 素数判定 2
转载自:http://www.dxmtb.com/blog/miller-rabbin/ 普通的素数测试我们有O(√ n)的试除算法.事实上,我们有O(slog³n)的算法. 定理一:假如p是质数,且 ...
- poj 2528 Mayor's posters 线段树区间更新
Mayor's posters Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://poj.org/problem?id=2528 Descript ...
- Pandas中Series和DataFrame的索引
在对Series对象和DataFrame对象进行索引的时候要明确这么一个概念:是使用下标进行索引,还是使用关键字进行索引.比如list进行索引的时候使用的是下标,而dict索引的时候使用的是关键字. ...
- mui中a标签的跳转问题
一.脑补 快速响应是mobile App实现的重中之重,研究表明,当延迟超过100毫秒,用户就能感受到界面的卡顿,然而手机浏览器的click点击存在300毫秒延迟(至于为何会延迟,及300毫秒的来龙去 ...