关系型数据通常以规范化情势保存,就是说你应该尽可能少地重复数据;通常情况下,表与表之间仅通过各种键值实现关联。进一步地讲,规范化的含义就是:你不能在数据库中保存计算后的值,而你只能在必要的时候一时计算数据库中保存的值。=GE0TT+~a^Gg8-| 8
对数据进行某些分析通常是很紧张的。比方说,你或许想知道哪些产品的定单最多或者哪些定单的利润最大。这些题目都要求你针对本身的SQL语句创建实行过滤规则的公式。其中最紧张的语句之一就是GROUP BY子句。;F~M_j?3}C;K,n-=d
Northwind数据库中的定单UX8{TN6P_7# P&\
Northwind数据库是包含在SQL Server安装软件中的两个示范数据库。这个数据库虽然谈不上完善完好但也充足知足我们讨论GROUP BY语句的目的了。缘故原由之一是它工作原理清晰,运行优秀,包含了一整套标准的数据表,比如Customers(客户)、Orders(定单)、Order Details(定单细节)和处理定单的Products(产品)。n= /€*K:PZmYz`kL
表的结构模式}dX?H€0i/;p{7b^,
假如你想查看各个定单的OrderID和ProductID ,以下的SQL饬令可以知足要求:S?Q-tE:Ocpk, em ]
=ab)yNkWp;e3_ SELECT o.OrderID, od.ProductID vG)=)gC"a]\_L;6g'( FROM Orders o, [Order Details] od 8K^z@E)frIqS1o WHERE o.OrderID = od.OrderID |
如许你就通过OrderID字段把Orders和Order Details连接了起来。给出的效果列表即表现各定货条款的OrderID和ProductID。-ZH]X.k40.y~eWwBF@
你可以从这个列表中找到条款数量最大的定单。可是,再想想,要能简单地要求数据库计算出必要的条款数目不更方便吗?假如你不关心单个条款而只想知道订购条款数量最大的定单,那么你可以采用以下的SQL语句:AP"HSr3&I@h~lhB
U=XEfL1 prp`grZ! SELECT o.OrderID, Count(od.ProductID) as NumItems o~73B"&iLVz?LPg FROM Orders o, [Order Details] od vyx+ H),,%g6yT/Y? WHERE o.OrderID = od.OrderID |
如许就可以总计出产品的数量并用一个名为NumItems的新字段来表现总数。可是,假如你实行该语句则可能得到以下错误:|kzo€rE ]yy8VQT?
Server: Msg 8118, Level 16, State 1, Line 1/e)jf/t?'Nd.HsE
选择语句中的'o.OrderID'列是无效的,由于它没有包含在汇集函数之内而且没有响应的GROUP BY 子句。bJp#^O*L*72G!X
在这种情况下,你现实上在总计ProductID,但OrderID却没有被计算总和或者有其他操作施加于其上。tQ=%C`;KKs-f"ku$I}
其实这个示例中计算的并不是订购产品条款的总数而是特定订购产品条款的数目。换句话说,你可以看到某一特定定单包括三种产品,但却并不能透露表现客户各订购了5种。你得到的正是按照定单统计的产品总量。你应该用GROUP BY字句来查看订购产品的总数。Oz%mW)}?r?"7s)DQJ
使用GROUP BYX9Yr3c0=oP)L/+2
使用GROUP BY就好比提出下面的题目:“我如何查看数据?“假如答案是“按照”某种要素来看那么你就可能用到GROUP BY。就我们的例子来说,你盼望按照定单查看产品的数量,所以你就可以用OrderID字段进行分组。此外,采用ORDER BY 子句可以更容易地找出订购条款最多的定单。新的查询语句如下所示:UHg[f
e5~mX,JUg7Tn
SELECT o.OrderID, Count(od.ProductID) as NumItems '\2ZbeAX?X
FD
FROM Orders o, [Order Details] od "zxA^VW
\TX
WHERE o.OrderID = od.OrderID $l/M5qMc?? RKq,\y
GROUP BY o.OrderID r;g0b8,J{Z0&C
ORDER BY NumItems DESC_IV(z€s$0$:fl
如今你就得到题目的答案了。如图B所示的部分效果,定单号11077订购了25种产品,而排第2的最大定单则只订购了6类产品。etp=kzGpB~j|%€
理解规则}QM[Z=oa$gpz+~FHo
GROUP BY具有相称高的天真性,当然你还得遵守响应的语法规则。比如说,你可以在ORDER BY 子句中包含多个表列。假如你想查看每一客户订购产品各个类型的数量,那么你必须通过定单创建查询把客户连接到产品。图A表现的4表连接显然就要用到了。之后你要根据客户和产品进行分组同时对Order Details表内的Quantity列计算总和。查询语句如下:K9|CAivAHTCSA{;F}
][e8azm.G??#'YT SELECT c.CompanyName, p.ProductName, Sum(od.Quantity) as TotalBought 00 qw79@|mfmz4E" FROM Customers c, Products p, Orders o, [Order Details] od 3$H =.SyZn[cwm WHERE Kky;ZTOw.lR@ } . c.CustomerID=o.CustomerID AND :(;%Y]+6yzi=}F#\Z o.OrderID=od.OrderID AND 3f\'7MtEz@y$UsP od.ProductID=p.ProductID x=Q%PTN 0%+"|(xX(& GROUP BY c.CompanyName, p.ProductName ;Fa2#"f1€bs04? ORDER BY CompanyName, TotalBought DESC |
查询效果表现出数据库内每一客户购买各类产品的总数。h*8-Ws'qyga BA]y
同时,你还可以在查询中置入多个汇集列。例如,假设你想查看的定单列表要表现单一项目的最大购买量以及该定单的项目总数,那么以下的语句就可以用Max函数来表现单一项目的最大订购量。这种方法还能对所购项目总量求和。3Q%T .Gh[?,vR&.]qi
$Y[,qOAlw1bjJI SELECT o.OrderID, hWe~_UaHg&Pt}hq? Max(od.Quantity) as TopItem, h@O1€c..8W9t]*$({ Sum(od.Quantity) as TotalBought A*UY*WFq1@C`o'] FROM d:WIMh!BRC!,t^p€ Orders o, Y&O_ig7 K1N;k'*: [Order Details] od, MUz0^L&e;V$uTOb Products p xBU.)!j'AyWg `? WHERE P Mqje{z0#*IiL2K6 o.OrderID = od.OrderID AND k_};N!~z36.x][s1 od.ProductID=p.ProductID :H=@kD?pPSy1f'[?1q GROUP BY o.OrderID Y((F)O[r2;?j{n,p ORDER BY TotalBought DESC |
如今你得到了定单、订购量排前列的数量以及定单总项。}nDUxu]?&D![~)
GROUP BY是过滤数据的一种强有力的工具。为了在你的SQL表内计算数据,它的功能不可鄙视。A'vVbM,Bs{.j yM
上一篇:3000.net 的 7.53 曩昔老版本如何升级到 8.53 online ? | 下一篇:SQL查询慢的48个缘故原由分析 |