您的位置:首页 > 其它

Group by与having理解

2011-10-14 10:54 204 查看
注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里。

1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用

group by 有一个原则,就是 select 后面的所有列中,没有使用聚合函数的列,必须出现在 group by 后面(重要)

例如,有如下数据库表:

A B

1 abc

1 bcd

1 asdfg

如果有如下查询语句(该语句是错误的,原因见前面的原则)

select A,B from table group by A

该查询语句的意图是想得到如下结果(当然只是一相情愿)

A B

abc

1 bcd

asdfg

右边3条如何变成一条,所以需要用到聚合函数,如下(下面是正确的写法):

select A,count(B) as 数量 from table group by A

这样的结果就是

A 数量

1 3

2. Having

where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行。

having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件显示特定的组,也可以使用多个分组标准进行分组。

having 子句被限制在SELECT语句中定义的列和聚合表达式上。通常,你需要通过在HAVING子句中重复聚合函数表达式来引用聚合值,就如你在SELECT语句中做的那样。例如:

SELECT A COUNT(B) FROM TABLE GROUP BY A HAVING COUNT(B)>2

3.使用compute和compute by

使用compute子句允许同时观察查询所得到各列的数据的细节以及统计各列数据所产生的汇总列

select * from work [查询所得到的各列的数据的细节]

compute max(基本工资),min(基本工资) [统计之后的结果]

这个例子中没有使用by关键字,返回的结果是最后添加了一行基本工资的最大值和最小值,也可增加by关键字.

例:select * from work order by 学历

compute max(基本工资),min(基本工资) by 学历

比较:select 学历,max(基本工资),min(基本工资) from work group by 学历

说明:1:compute子句必须与order by子句用在一起

2:compute子句可以返回多种结果集.一种是体现数据细节的数据集,可以按分类要求进行正确的分类;另一种在分类的基础上进行汇总产生结果.

3:而group by子句对每一类数据分类之后只能产生一个结果,不能知道细节

示例学习Northwind数据库:

① Categories:种类表
相应字段:
CategoryID :类型ID;
CategoryName:类型名;
Description:类型说明;
Picture:产品样本
② CustomerCustomerDemo:客户类型表1
相应字段:
CustomerID:客户ID;
CustomerTypeID:客户类型ID
③ CustomerDemographics:客户类型表2
相应字段:
CustomerTypeID:客户类型ID;
CustomerDesc:客户描述
④ Customers:客户表
相应字段:
CustomerID:客户ID;
CompanyName:所在公司名称;
ContactName:客户姓名;
ContactTitle:客户头衔;
Address:联系地址;
City:所在城市;
Region:所在地区;
PostalCode:邮编;
Country:国家
Phone:电话;
Fax:传真
⑤ Employees:员工表
相应字段:
EmployeeID:员工代号;
LastName + FirstName员工姓名;
Title:头衔;
TitleOfCourtesy:尊称;
BirthDate:出生日期;
HireDate:雇用日期;
Address:家庭地址;
City:所在城市;
Region:所在地区;
PostalCode:邮编;
Country:国家用;
HomePhone:宅电;
Extension:分机;
Photo:手机;
notes:备注;
ReportsTo:上级;
PhotoPath:照片
⑥ EmployeeTerritories:员工部门表
相应字段:
EmployeeID:员工编号;
TerritoryID:部门代号
⑦ Order Details:订单明细表
相应字段:
OrderID:订单编号;
ProductID:产品编号;
UnitPrice:单价;
Quantity:订购数量;
Discount:折扣
⑧ Orders:订单表
相应字段:
OrderID:订单编号;
CustomerID:客户编号;
EmployeeID:员工编号;
OrderDate:订购日期;
RequiredDate:预计到达日期;
ShippedDate:发货日期;
ShipVia:运货商;
Freight:运费;
ShipName:货主姓名;
ShipAddress:货主地址
ShipCity:货主所在城市;
ShipRegion:货主所在地区;
ShipPostalCode:货主邮编;
ShipCountry:货主所在国家
⑨ Products:产品表
相应字段:
ProductID:产品ID;
ProductName:产品名称;
SupplierID:供应商ID;
CategoryID:类型ID;
QuantityPerUnit:数量;
UnitPrice:单价;
UnitsInStock:库存数量;
UnitsOnOrder:订购量;
ReorderLevel:再次订购量;
Discontinued:中止
⑩ Region:地区表
相应字段:
RegionID:地区ID;
RegionDescription:地区描述
11、Shippers:运货商
相应字段:
ShipperID:运货商ID;
CompanyName:公司名称;
Phone:联系电话
12、Suppliers:供应商表
相应字段:
ShipperID:供应商ID;
CompanyName:供应商姓名;
Phone;联系电话
13、Territories:地域表
相应字段:
TerritoryID:地域编号;
TerritoryDescription:地域描述;
RegionID:地区编号

非相关查询:

1:返回每个美国员工都为其处理过订单的所有客户
--思路:1:Employees表中获取美国员工总数2:Orders表中查询美国员工处理的Order,对CustomerID分组后,统计其不同的EmployeeID正好等于美国员工总数
Select CustomerID From Orders Where EmployeeID In --得到美国员工服务 的客户
(Select EmployeeID From Employees Where Country='USA') -- 得到全部美国员工id
group by CustomerID --按客户分组
Having Count(Distinct EmployeeID)= --为其处理订单的distinct 员工数等于美国总员工数
(Select Count(*) From Employees Where Country=N'USA')--美国员工总数
2:
返回在每月最后实际订单日期发生的订单(每月最后订单日期可能不是每月最后一天)
--思路:子查询按月分组得到每月最近订单日期
Select OrderID,CustomerID,EmployeeID,OrderDate
From Orders
Where OrderDate In
(Select Max(OrderDate) From Orders Group by Convert(char(6),OrderDate,112))--112表示YYYYMMDD char(6)提取YYYYMM
3.

Select字句在逻辑上是SQL语句最后进行处理的最后一步,所以,以下查询会发生错误:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts

FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID

FROM dbo.Orders) AS D

GROUP BY OrderYear

;因为group by是在Select之前进行的,那个时候orderYear这个列并没有形成。

如果要查询成功,可以像下面进行修改:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts

FROM (SELECT YEAR(OrderDate) AS OrderYear, CustomerID

FROM dbo.Orders) AS D

GROUP BY OrderYear;还有一种很特殊的写法:

SELECT OrderYear, COUNT(DISTINCT CustomerID) AS NumCusts

FROM (SELECT YEAR(OrderDate), CustomerID

FROM dbo.Orders) AS D(OrderYear, CustomerID)

GROUP BY OrderYear;在作者眼里,他是非常喜欢这种写法的,因为更清晰,更明确,更便于维护。

在查询中使用参数定向产生一批结果,这个技巧没有什么好说的。

嵌套查询,在处理逻辑上是从里向外进行执行的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: