SQLgroupby分组查询
本⽂导读:在实际SQL应⽤中,经常需要进⾏分组聚合,即将查询对象按⼀定条件分组,然后对每⼀个组进⾏聚合分析。创建分组是通过GROUP BY⼦句实现的。与WHERE⼦句不同,GROUP BY⼦句⽤于归纳信息类型,以汇总相关数据。GROUP BY的作⽤是通过⼀定的规则将⼀个数据集划分成若⼲个⼩的区域,然后针对若⼲个⼩区域进⾏数据处理。
在SQL Server中使⽤的分组查询是ORDER BY⼦句,使⽤ORDER BY⼦句要同聚合函数配合使⽤才能完成分组查询,在SELECT查询的字段中如果字段没有使⽤聚合函数就必须出现在ORDER BY⼦句中(即SELECT后边的字段名要么出现在聚合函数中,要么在ORDER BY⼦句中使⽤)
在分组查询中还可以配合使⽤HAVING⼦句,定义查询条件。
使⽤group by进⾏分组查询
在使⽤group by关键字时,在select列表中可以指定的项⽬是有限制的,select语句中仅许以下⼏项:
〉被分组的列
〉为每个分组返回⼀个值得表达式,例如⽤⼀个列名作为参数的聚合函数
group by 有⼀个原则,就是 select 后⾯的所有列中,没有使⽤聚合函数的列,必须出现在 group by 后⾯(重要)
group by实例
实例⼀
数据表:
姓名科⽬分数
张三语⽂ 80
张三数学 98
张三英语 65
李四语⽂ 70
李四数学 80
李四英语 90
期望查询结果:
姓名语⽂数学英语
张三 80 98 65
李四 70 80 90
代码
SQL 代码复制
create table testScore
(
tid int primary key identity(1,1),
tname varchar(30) null,
ttype varchar(10) null,
tscor int null
)
go
---插⼊数据
insert into testScore values ('张三','语⽂',80)
insert into testScore values ('张三','数学',98)
insert into testScore values ('张三','英语',65)
insert into testScore values ('李四','语⽂',70)
insert into testScore values ('李四','数学',80)
insert into testScore values ('李四','英语',90)
select tname as '姓名' ,
max(case ttype when '语⽂' then tscor else 0 end) '语⽂',
max(case ttype when '数学' then tscor else 0 end) '数学',
max(case ttype when '英语' then tscor else 0 end) '英语'
from testScore
group by tname
实例⼆
有如下数据:(为了看得更清楚,我并没有使⽤国家代码,⽽是直接⽤国家名作为Primary Key)
groupby分组国家(country)⼈⼝(population)
中国600
美国100
加拿⼤100
英国200
法国300
⽇本250
德国200
墨西哥50
印度250
根据这个国家⼈⼝数据,统计亚洲和北美洲的⼈⼝数量。应该得到下⾯这个结果。
洲⼈⼝
亚洲1100
北美洲250
其他700
代码
SQL 代码复制
SELECT  SUM(population),
CASE country
WHEN '中国'    THEN '亚洲'
WHEN '印度'    THEN '亚洲'
WHEN '⽇本'    THEN '亚洲'
WHEN '美国'    THEN '北美洲'
WHEN '加拿⼤'  THEN '北美洲'
WHEN '墨西哥'  THEN '北美洲'
ELSE '其他' END
FROM    Table_A
GROUP BY CASE country
WHEN '中国'    THEN '亚洲'
WHEN '印度'    THEN '亚洲'
WHEN '⽇本'    THEN '亚洲'
WHEN '美国'    THEN '北美洲'
WHEN '加拿⼤'  THEN '北美洲'
WHEN '墨西哥'  THEN '北美洲'
ELSE '其他' END;
同样的,我们也可以⽤这个⽅法来判断⼯资的等级,并统计每⼀等级的⼈数。SQL代码如下;SQL 代码复制
SELECT
CASE WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600  THEN '2'
WHEN salary > 600 AND salary <= 800  THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END salary_class,
COUNT(*)
FROM    Table_A
GROUP BY
CASE WHEN salary <= 500 THEN '1'
WHEN salary > 500 AND salary <= 600  THEN '2'
WHEN salary > 600 AND salary <= 800  THEN '3'
WHEN salary > 800 AND salary <= 1000 THEN '4'
ELSE NULL END;
对于groupby后⾯⼀般都是跟⼀个列名,但在该例⼦中通过case语句使分组变得跟强⼤了。
实例三
有如下数据
国家(country)性别
(sex)
⼈⼝
(population)
中国1340
中国1340
中国2260
美国145
美国255
加拿⼤151
加拿⼤249
英国140
英国260
按照国家和性别进⾏分组,得出结果如下
国家男⼥
中国340260
美国4555
加拿⼤5149
英国4060
代码
SQL 代码复制
SELECT country,
SUM( CASE WHEN sex = '1' THEN
population ELSE 0 END),  --男性⼈⼝
SUM( CASE WHEN sex = '2' THEN
population ELSE 0 END)  --⼥性⼈⼝
FROM  Table_A
GROUP BY country;
GROUP BY⼦句中的NULL值处理
当GROUP BY⼦句中⽤于分组的列中出现NULL值时,将如何分组呢?SQL中,NULL不等于NULL(在WHERE⼦句中有过介绍)。然⽽,在GROUP BY⼦句中,却将所有的NULL值分在同⼀组,即认为它们是“相等”的。
HAVING⼦句
GROUP BY⼦句分组,只是简单地依据所选列的数据进⾏分组,将该列具有相同值的⾏划为⼀组。⽽实际应⽤中,往往还需要删除那些不能满⾜条件的⾏组,为了实现这个功能,SQL提供了HAVING⼦句。语法如下。
SELECT column, SUM(column)
FROM table
GROUP BY column
HAVING SUM(column) condition value
说明:HAVING通常与GROUP BY⼦句同时使⽤。当然,语法中的SUM()函数也可以是其他任何聚合函数。DBMS将HAVING⼦句中的搜索条件应⽤于GROUP BY⼦句产⽣的⾏组,如果⾏组不满⾜搜索条件,就将其从结果表中删除。
HAVING⼦句的应⽤
从TEACHER表中查询⾄少有两位教师的系及教师⼈数。
实现代码:
SQL 代码复制
SELECT DNAME, COUNT(*) AS num_teacher
FROM TEACHER
GROUP BY DNAME
HAVING COUNT(*)>=2
HAVING⼦句与WHERE⼦句的区别
HAVING⼦句和WHERE⼦句的相似之处在于,它也定义搜索条件。但与WHERE⼦句不同,HAVING⼦句与组有关,⽽不是与单个的⾏有关。
1、如果指定了GROUP BY⼦句,那么HAVING⼦句定义的搜索条件将作⽤于这个GROUP BY⼦句创建的那些组。
2、如果指定WHERE⼦句,⽽没有指定GROUP BY⼦句,那么HAVING⼦句定义的搜索条件将作⽤于WHERE⼦句的输出,并把这个输出看作是⼀个组。
3、如果既没有指定GROUP BY⼦句也没有指定WHERE⼦句,那么HAVING⼦句定义的搜索条件将作⽤于FROM⼦句的输出,并把这个输出看作是⼀个组。
4、在SELECT语句中,WHERE和HAVING⼦句的执⾏顺序不同。在本书的.1.2节介绍的SELECT语句的执⾏步骤可知,WHERE⼦句只能接收来⾃FROM⼦句的输⼊,⽽HAVING⼦句则可以接收来⾃GROUP BY⼦句、WHERE⼦句和FROM⼦句的输⼊。
5)
-- group by  ....  with rollup 的使⽤
CREATE TABLE #test (
Name  varchar(10)
,  [procedure] CHAR(1)
,  model  varchar(5)
,  quantity  int);
INSERT intO #testSELECT  'A', '1', 'φ',  500
union ALLSELECT  'A', '1', 'φ',  600
union ALLSELECT  'A', '1', 'φ', 500
union ALLSELECT  'A', '2', 'φ',  700
union ALLSELECT  'A', '2', 'φ', 200
union ALLSELECT  'B', '1', 'φ',  1000;
SELECT
case WHEN GROUPING(Name) = 1 THEN  '总计'
WHEN GROUPING(Name) = 0 AND GROUPING([procedure]) = 1 THEN  Name + '合计'
WHEN GROUPING(Name) = 0 AND GROUPING([procedure]) = 0 AND GROUPING([model]) = 1 THEN  Name + '的' + [procedure] + '⼩计'
else  Name  end  AS  Name
,  case WHEN GROUPING([model]) = 1 THEN '' else [procedure]  end  AS  [procedure]
,  isnull(model, '') AS model
,  sum(quantity) AS quantity

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。