本文导读:在实际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)

国家(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)

中国

1

340

中国

2

260

美国

1

45

美国

2

55

加拿大

1

51

加拿大

2

49

英国

1

40

英国

2

60

按照国家和性别进行分组,得出结果如下

国家

中国

340

260

美国

45

55

加拿大

51

49

英国

40

60

代码

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

FROM  #test

group by   Name,  [procedure], model with rollup

procedure model quantity----------------- --------- ----- ----------

-A                 1         φ          500

A                 1         φ          1100

A的小计                                    1600

A                 2         φ          200

A                 2         φ           700

A的小计                                     900

A合计                                      2500

B                 1         φ          1000

B的小计                                    1000

B合计                                      1000

总计                                       3500

CUBE运算符生成的结果集是多维数据集,多维数据集是事实数据的扩展,事实数据即记录个别时间的数据,扩展建立在用户准备分析的列上,这些列被称为维,多维数据集是一个结果集,其中包含各纬度所有可能的交叉表格.

CUBE运算符是在Select语句的group by子句中指定的,group by应指定维度列和关键字with cube,结果集将包括维度列中各值的所有可能组合.

示例1.

Sql语句如下:

select * from student

select sex,sclass,sum(score) as 合计

from student

group by sex,sclass with cube

select sex,sclass,sum(score) as 合计

from student

group by sclass,sex with cube

Sql查询时这样运行:

1. 查询到性别的第一个性别为男,则先查询男生,然后分班级

2. 查询完成之后,对性别为Sex为男的数据进行合计

3. 查询性别为女的数据,查询完成之后同样也进行合计

4. 不分性别、班级进行合计汇总

5. 以上均是以性别为组来分类,因为至此时关于性别的所有汇总都已经完成

6. 按照sclass进行分组汇总.

注意:

1. 分类依据并不是根据select 中的顺序,而是根据group by中的顺序.

2. 尽量按照使select和group by中的字段顺序一致,这样在显示起来看着更舒服,具体情况具体分析.

对于上述查询的结果,我们可以看出,数据中存在空置问题,绑定到GridView后显示如下:

此中效果并没有达到能够满足实际项目中的需要,所以,我们对Sql语句应进行改进.

使用Grouping区分空值.

如何区分使用CUBE之后产生的空值和实际查询中得到的空值.这个问题可以用grouping函数来解决.如果列中的值来来自查询数据,则grouping返回0,如果列中的值是cube产生的空值,则返回1

示例2.

Sql如下:

select case when(grouping(sex)=1) then '小记' else sex

end as 性别,

case when(grouping(sclass)=1) then '小记' else sclass

end as 班级,

sum(score)

from student

group by sex,sclass with cube

在页面上显示时如下:

CUBE可以生成n维的多维数据集,即具有任意维目的多维数据集,只有一个维度的多维数据集可用于生成合计.

示例3:

SQL:

select case when(grouping(sex)=1) then '合计' else sex end as 性别,

sum(score) as 合计

from student

group by sex with cube

生成许多维度的数据集合结果可能很大,办法就是生成一个大的视图,选择显示即可.

文章出处:http://www.studyofnet.com/news/247.html

SQL group by分组查询的更多相关文章

  1. SQL group by分组查询(转)

    本文导读:在实际SQL应用中,经常需要进行分组聚合,即将查询对象按一定条件分组,然后对每一个组进行聚合分析.创建分组是通过GROUP BY子句实现的.与WHERE子句不同,GROUP BY子句用于归纳 ...

  2. Group by 分组查询 实战

    实战经历,由于本人在共享单车上班,我们的单车管理模块,可以根据单车号查询单车,但是单车号没有设置unique(独一无二约束),说以这就增加了单车号可能重复的风险,但是一般情况下,单车号是不会重复的,因 ...

  3. 【mybatis】【mysql】mybatis查询mysql,group by分组查询报错:Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column

    mybatis查询mysql,group by分组查询报错:Expression #1 of SELECT list is not in GROUP BY clause and contains no ...

  4. mysql group by分组查询后 查询个数

    mysql group by分组查询后 查询个数2个方法随便你选 <pre>select count(distinct colA) from table1;</pre>< ...

  5. 【Oracle命令 】使用的sql语句之分组查询(group by)

    由于本人并未对oracle数据库进行深入了解,但是工作中又需要知道一些基础的sql,所以记录下操作的sql语句.方便日后查看 1.将序列号作为分组查询的条件,再将查询出来的结果进行筛选. select ...

  6. ysql常用sql语句(12)- group by 分组查询

    测试必备的Mysql常用sql语句,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1683347.html 前言 ...

  7. mysql group by分组查询

    分组的SQL语句有2个: group by 和分组聚合函数实现 partition by (oracle和postgreSQL中的语句)功能 group by + having 组合赛选数据 注意:h ...

  8. group by分组查询

    有如下数据: 一个简单的分组查询的案例 按照部门编号deptno分组,统计每个部门的平均工资. select deptno,avg(sal) avgs from emp group by deptno ...

  9. oracle Group by 分组查询后,分页

    ------------恢复内容开始------------ 1.分页查询 select count(*) times,title from menulog group by title order ...

随机推荐

  1. docker 搭建gitlab

    https://docs.gitlab.com/omnibus/docker/ https://blog.csdn.net/m0_37444820/article/details/81147452 h ...

  2. Java 类装载器工作机制

    类装载器就是寻找类的字节码文件并构造出类在JVM内部表示的对象组件.在java中,类装在器把一个类装入JVM中,要经过以下几个步骤: 1.装载:查找和导入Class文件 2链接:执行校验,准备和解析步 ...

  3. delphi 按钮 2 行

    http://bbs.csdn.net/topics/390230792 回复于: 2015-06-01 21:11:02 最简单的办法:------------------------以下是转载的, ...

  4. curl 中关于 CURLINFO_HEADER_SIZE 的 BUG 定位及修复

    curl 官方下载页面 CentOS7 默认安装的 curl 版本太低了,需要升级为最新版. 1. 问题描述 对接了一个接口,用来下载 PDF 文件.使用 curl 下载后,文件老是报错无法打开.接口 ...

  5. 页面跳转(包括vue路由)

    1.JS实现页面跳转 1.1 使用window.location的href属性跳转 window.location.href = 'http://www.baidu.com';此处window可以省略 ...

  6. Java8 Nashorn JavaScript引擎

    使用Java8,Nashorn大大提高了JavaScript 引擎引入,以取代现有的Nashorn Java脚本引擎.Nashorn提供2至10倍更好的性能,因为它直接编译代码在存储器,并传递到字节码 ...

  7. JavaWeb防止用户的重复请求提交

    这里实现这个重复提交的防止,是通过在一个FIlter过滤器中生成一个令牌token,保存在Session域中,然后在对这个token加密得到ciphertext(密文),将密文保存在request域中 ...

  8. python网络编程之粘包

    一.什么是粘包 须知:只有TCP有粘包现象,UDP永远不会粘包 粘包不一定会发生 如果发生了:1.可能是在客户端已经粘了 2.客户端没有粘,可能是在服务端粘了 首先需要掌握一个socket收发消息的原 ...

  9. P2634 [国家集训队]聪聪可可(题解)(点分治)

    P2634 [国家集训队]聪聪可可(题解)(点分治) 洛谷题目 #include<iostream> #include<cstdlib> #include<cstdio& ...

  10. Zookeeper-技术专区-配置以及学习

    zookeeper 一.zookeeper下载 zookeeper下载可以直接去官网进行下载  https://zookeeper.apache.org/releases.html ,可以选择最新版本 ...