先來建立一個測試表javascript
1 USE [tempdb] 2 GO 3 4 CREATE TABLE #temptb(id INT ,NAME VARCHAR(200)) 5 GO 6 7 INSERT INTO [#temptb] ( [id], [NAME] ) 8 SELECT 1,'中國' UNION ALL 9 SELECT 2,'中國' UNION ALL 10 SELECT 3,'英國' UNION ALL 11 SELECT 4,'英國' UNION ALL 12 SELECT 5,'美國' UNION ALL 13 SELECT 6,'美國' UNION ALL 14 SELECT null, '法國' UNION ALL 15 SELECT 8,'法國' 16 GO 17 18 SELECT * FROM [#temptb] 19 GO
先來看一下SELECT語句的語法:html
1 SELECT [ ALL | DISTINCT ] [ topSubclause ] aliasedExpr 2 [{ , aliasedExpr }] FROM fromClause [ WHERE whereClause ] [ GROUP BY groupByClause [ HAVING havingClause ] ] [ ORDER BY orderByClause ] 3 or 4 SELECT VALUE [ ALL | DISTINCT ] [ topSubclause ] expr FROM fromClause [ WHERE whereClause ] [ GROUP BY groupByClause [ HAVING havingClause ] ] [ ORDER BY orderByClause
ALL關鍵字:指定在結果集中能夠顯示重複的行,這是默認的關鍵字,也就是說,當您在查詢中不使用ALL關鍵字,默認都已經附加上了ALL這個關鍵字java
例以下面兩個SQL語句,其實是等價的,都會把重複的記錄select出來web
1 --這兩個語句是等價的 2 SELECT * FROM [#temptb] 3 GO 4 ------------------------------------------- 5 SELECT ALL * FROM [#temptb] 6 GO
若是您須要把惟一值select出來,過濾掉那些重複值須要使用DISTINCT關鍵字sql
1 SELECT DISTINCT([NAME]) FROM [#temptb]
而當您把SQL語句,字段放在ALL括號中,這時候就會變成一個表達式,例以下面SQL語句服務器
1 SELECT ALL([NAME]+'您好') AS '國別' FROM [#temptb]
在我上一篇文章裏:處理表重複記錄(查詢和刪除)ide
在Name相同ID最大的記錄,其中有一個SQL語句函數
1 SELECT * 2 FROM [#temptb] a 3 WHERE ID!<ALL ( SELECT ID 4 FROM [#temptb] 5 WHERE Name = a.Name )
若是去掉ALL關鍵字會怎樣呢?post
由於子查詢須要的是一個表達式,因此須要使用ALL關鍵字把他變爲一個表達式,因此要用ALL測試
ALL關鍵字還能夠放在GROUP BY 以後
這裏要分兩種狀況,一種是SQL語句中有where子句的的,另外一種是SQL語句中沒有where子句的
狀況一:
1 SELECT AVG(id) FROM [#temptb] WHERE NAME='法國' GROUP BY ALL NAME 2 SELECT AVG(id) FROM [#temptb] WHERE NAME='法國' GROUP BY NAME
對於沒有符合條件的行的組,這裏是沒有符合name='法國',做爲聚合值的列值爲NULL
若是沒有ALL關鍵字,GROUP BY子句將不顯示沒有符合條件的行的組
狀況二:
1 SELECT AVG(id) FROM [#temptb] GROUP BY ALL NAME 2 SELECT AVG(id) FROM [#temptb] GROUP BY NAME
當SQL語句中沒有where子句的時候,查詢出來的結果都是同樣的
ALL關鍵字還能夠放在UNION以後
1 USE [GPOSDB] 2 GO 3 INSERT INTO [dbo].[SystemPara] ( [ParaValue], [Name], [Description] ) 4 SELECT 'nihao','nihao','nihao' UNION ALL 5 SELECT 'nihao','nihao','nihao'
PERCENT關鍵字
PERCENT關鍵字須要跟TOP 關鍵字一塊兒使用
從結果集中輸出百分之N行,n必須是介於0~100之間的整數
1 SELECT TOP 10 PERCENT * from [#temptb] 2 GO
上面的SQL語句意思是:從[#temptb]表中輸出10%的記錄數,由於沒有使用order by子句,因此這條記錄是隨機的
由於[#temptb]表有8條記錄,8*10%=0.8 四捨五入以後至關於一條記錄
1 SELECT TOP 30 PERCENT * from [#temptb] 2 GO
8*30%=2.4 四捨五入以後至關於三條記錄,SQLSERVER在這裏就算四捨五入不足三條記錄,他也會輸出偏大的數,也就是三條記錄
CUBE關鍵字
CUBE關鍵字:若是須要在結果集內不只包含由GROUP BY提供的正常行,還包含彙總行,能夠用CUBE關鍵字。CUBE關鍵字與GROUP BY一塊兒使用
當使用CUBE關鍵字的時候,可使用GROUPING函數來輸出一個額外的列,當結果行是正常的行時,返回0;當結果行是彙總行時,返回1。
1 SELECT AVG(id) AS '平均值', GROUPING(NAME) AS '是否已彙總' 2 FROM [#temptb] 3 GROUP BY NAME 4 WITH CUBE
最後一行顯示了GROUP BY的記錄有多少行,一共有4行記錄,而在彙總行(即最後一行)是否已彙總那列顯示1,表示是彙總行
Grouping關鍵字
指示是否聚合 GROUP BY 列表中的指定列表達式。
在結果集中,若是 GROUPING 返回 1 則指示聚合;返回 0 則指示不聚合。
若是指定了 GROUP BY,則 GROUPING 只能用在 SELECT <select> 列表、HAVING 和 ORDER BY 子句中。
http://msdn.microsoft.com/zh-cn/library/ms178544(v=sql.105).aspx
GROUPING 用於區分標準空值和由 ROLLUP、CUBE 或 GROUPING SETS 返回的空值。
做爲 ROLLUP、CUBE 或 GROUPING SETS 操做結果返回的 NULL 是 NULL 的特殊應用。
它在結果集內做爲列的佔位符,表示全體。
如下示例將分組 SalesQuota 並聚合 SaleYTD 數量。GROUPING 函數應用於 SalesQuota 列。
1 USE [AdventureWorks]; 2 GO 3 SELECT SalesQuota, SUM(SalesYTD) 'TotalSalesYTD', 4 GROUPING(SalesQuota) AS 'Grouping' 5 FROM Sales.SalesPerson 6 GROUP BY SalesQuota 7 WITH ROLLUP; 8 GO
結果集在 SalesQuota 下面顯示兩個空值。
第一個 NULL 表明從表中的這一列獲得的空值組。
第二個 NULL 位於 ROLLUP 操做所添加的彙總行之中。
彙總行顯示全部 SalesQuota 組的 TotalSalesYTD 數量,並以 Grouping 列中的 1 進行指示。
http://msdn.microsoft.com/zh-cn/library/ms191500(v=sql.100).aspx
對簡單彙總報表使用 Transact-SQL
生成簡單彙總報表的應用程序可以使用下列 Transact-SQL 元素:
ROLLUP、CUBE 或 GROUPING SETS 運算符。這些是 SELECT 語句的 GROUP BY 子句的擴展。
COMPUTE 或 COMPUTE BY 運算符。這兩種運算符也與 GROUP BY 相關聯。
這些運算符生成的結果集中,既包含每一個項目的明細行,也包含每一個組的彙總行,彙總行顯示了該組的聚合合計。
GROUP BY 子句可用於生成只包含各組的聚合而不包含其明細行的結果。
應用程序應使用 Analysis Services,而不是 CUBE、ROLLUP、COMPUTE 或 COMPUTE BY。
特別要注意的是,CUBE 和 ROLLUP 應當只用在沒法訪問 OLE DB 或 ADO 的環境中,例如腳本或存儲過程當中。
支持 COMPUTE 和 COMPUTE BY 是爲了向後兼容。
應當優先選用 ROLLUP 運算符而非 COMPUTE 或 COMPUTE BY。由 COMPUTE 或 COMPUTE BY 生成的彙總值將做爲多個單獨的結果集返回,
這些結果集之間還插入了包含各組明細行的結果集;或者做爲包含合計的結果集返回,附加在主結果集以後。
處理這些多個結果集將增長應用程序代碼的複雜性。服務器遊標既不支持 COMPUTE,也不支持 COMPUTE BY。
但 ROLLUP 支持服務器遊標。CUBE 和 ROLLUP 將生成單個結果集,其中包含嵌入的小計和合計行。
此外,查詢優化器有時還能夠爲 ROLLUP 生成比爲 COMPUTE 和 COMPUTE BY 生成的執行計劃更高效的執行計劃。
若是使用不帶這些運算符的 GROUP BY,將返回單個結果集,其中每組對應一行,行中包含該組的聚合小計。結果集中沒有明細行。
SQLSERVER中Cube 、RollUp的用法
Cube 、RollUp能夠對查詢的數據進行彙總,在數據統計中常常用到,尤爲是作報表時,用在Select語句中
下面就對兩種統計方式進行對比
SQL腳本以下:
1 USE [tempdb] 2 GO 3 CREATE TABLE t_test 4 ( 5 id INT , 6 productName VARCHAR(200) , 7 price MONEY , 8 num INT , 9 amount INT , 10 operatedate DATETIME 11 ) 12 GO 13 14 --插入隨機數據 15 DECLARE @i INT 16 DECLARE @rand MONEY 17 DECLARE @date DATETIME 18 DECLARE @index INT 19 DECLARE @DateBase INT 20 SET @date = '2012-10-23' 21 SET @i = 1 22 WHILE ( @i < 18 ) 23 BEGIN 24 SET @rand = RAND() * 20 25 SET @index = CAST(RAND() * 3 AS INT) 26 SET @DateBase = CAST(RAND() * 10 AS INT) 27 28 INSERT INTO t_test ( id, productName, price, num, amount, operatedate ) 29 VALUES ( @i, 'product' + CAST (@index AS VARCHAR(10)), @rand, 100, 30 @rand * 100, @date + @DateBase ) 31 SET @i = @i + 1 32 END 33 34 35 SELECT * FROM t_test
分別用兩種方式統計:
1 --分別用兩種方式統計: 2 3 SELECT CASE WHEN GROUPING(operatedate) = 1 THEN '小計' 4 ELSE CONVERT(VARCHAR(10), operatedate, 120) 5 END AS 日期, CASE WHEN GROUPING(productName) = 1 THEN '小計' 6 ELSE productName 7 END AS 產品名稱, SUM(amount) / SUM(num) AS 平均價格, SUM(num) AS 數量, 8 SUM(amount) AS 金額 9 FROM t_test 10 GROUP BY operatedate, productName WITH ROLLUP; 11 ------------------------------------------------------------------- 12 SELECT CASE WHEN GROUPING(operatedate) = 1 THEN '小計' 13 ELSE CONVERT(VARCHAR(10), operatedate, 120) 14 END AS 日期, CASE WHEN GROUPING(productName) = 1 THEN '小計' 15 ELSE productName 16 END AS 產品名稱, SUM(amount) / SUM(num) AS 平均價格, SUM(num) AS 數量, 17 SUM(amount) AS 金額 18 FROM t_test 19 GROUP BY operatedate, productName WITH CUBE;
ROLLUP 按照分組順序,先對第一個字段operatedate分組,在組內進行統計,最後給出合計
1 SELECT CASE WHEN GROUPING(operatedate) = 1 THEN '小計' --用GROUPING得出是不是彙總行,這個例子裏最後一行是彙總行 2 ELSE CONVERT(VARCHAR(10), operatedate, 120) 3 END AS 日期, CASE WHEN GROUPING(productName) = 1 THEN '小計' 4 ELSE productName 5 END AS 產品名稱, SUM(amount) / SUM(num) AS 平均價格, SUM(num) AS 數量, 6 SUM(amount) AS 金額 7 FROM t_test 8 GROUP BY operatedate, productName WITH ROLLUP; --由於operatedate和productName字段都在GROUPING函數裏統計是否彙總,因此GROUP BY後面就須要加operatedate和productName這兩個字段
CUBE 會對全部的分組字段進行統計,如上例,先對日期求小計,也就是統計天天的產品總金額,而後統計每一個產品的總金額,最後給出總的合計。
ROLLUP和CUBE的區別就是: ROLLUP 只會去統計group by 後面的第一個字段每一個分組的小計和第一個字段的總計
Grouping(字段名) 用來區分當前行是否是小計產生的行, Grouping(字段名)=1 說明是統計行,Grouping(字段名)=0 說明是表中行
能夠用在case,where 後面
http://www.2cto.com/database/201210/163455.html
另一個例子
SQL腳本以下:
1 USE [tempdb] 2 GO 3 CREATE TABLE Sales (EmpId INT, Yr INT, Sales MONEY) 4 INSERT Sales VALUES(1, 2005, 12000) 5 INSERT Sales VALUES(1, 2006, 18000) 6 INSERT Sales VALUES(1, 2007, 25000) 7 INSERT Sales VALUES(2, 2005, 15000) 8 INSERT Sales VALUES(2, 2006, 6000) 9 INSERT Sales VALUES(3, 2006, 20000) 10 INSERT Sales VALUES(3, 2007, 24000) 11 12 SELECT * FROM [dbo].[Sales]
ROLLUP
1 SELECT EmpId, Yr, SUM(Sales) AS Sales 2 FROM Sales 3 GROUP BY EmpId, Yr WITH ROLLUP
CUBE
1 SELECT EmpId, Yr, SUM(Sales) AS Sales 2 FROM Sales 3 GROUP BY EmpId, Yr WITH CUBE
CUBE比ROLLUP多了年份的統計,統計了200五、200六、2007年的銷售額
能夠用下圖來表示
ROLLUP
CUBE
http://blogs.msdn.com/b/craigfr/archive/2007/10/11/grouping-sets-in-sql-server-2008.aspx
驗證CUBE和ROLLUP 的區別
ROLLUP和CUBE的區別就是: ROLLUP 只會去統計group by 後面的第一個字段每一個分組的小計和第一個字段的總計
咱們修改一下上面那個實驗
1 USE [tempdb] 2 GO 3 CREATE TABLE Sales (EmpId INT,productName VARCHAR(200), Yr INT, Sales MONEY) 4 GO 5 INSERT Sales VALUES(1,'product2', 2005, 12000) 6 INSERT Sales VALUES(1,'product1', 2005, 18000) 7 INSERT Sales VALUES(1,'product0', 2006, 25000) 8 INSERT Sales VALUES(1,'product2', 2007, 15000) 9 INSERT Sales VALUES(2,'product1', 2005, 60000) 10 INSERT Sales VALUES(2,'product1', 2006, 22000) 11 INSERT Sales VALUES(2,'product0', 2007, 24000) 12 INSERT Sales VALUES(3,'product0', 2005, 32000) 13 INSERT Sales VALUES(3,'product2', 2006, 42000) 14 INSERT Sales VALUES(3,'product0', 2007, 24000) 15 GO 16 17 SELECT * FROM [dbo].[Sales]
ROLLUP
1 SELECT EmpId, Yr,[productName], SUM(Sales) AS Sales 2 FROM Sales 3 GROUP BY EmpId, Yr,[productName] WITH ROLLUP
CUBE
1 SELECT EmpId, Yr,[productName], SUM(Sales) AS Sales 2 FROM Sales 3 GROUP BY EmpId, Yr,[productName] WITH CUBE
能夠看到CUBE除了統計EmpId字段以外,還統計了GROUP BY後面的Yr和productName這兩個字段
而ROLLUP只統計了EmpId這個字段
總結
這些關鍵字和函數對平時用於統計的應用程序都很是有用,若是你們對這些函數功能都很熟悉的話,在開發當中必定可以駕輕就熟
另外,我的以爲PERCENT關鍵字能夠應用在分頁上
**********轉摘:https://www.cnblogs.com/lyhabc/archive/2013/08/25/3280634.html