SqlServer2008实例10汇总数据

    技术2022-07-10  198

    1.使用CUBE根据GROUP BY子句中的列来为结果集增加汇总值;

     CUBE为结果集增加行,根据GROUP BY子句巾的列来汇总总数值。下面示例演示了一个根据产品放置的货架束返回产品总数量的查询:

    SELECT i.Shelf,SUM(i.Quantity) Total FROM Production.ProductInventory i GROUP BY CUBE(i.Shelf)

    在下一个查询中,我们将LocationID增加剑SELECT和GROUP BY子句中:

    USE AdventureWorks go SELECT i.Shelf,i.LocationID,Sum(i.Quantity) Total FROM Production.ProductInventory i GROUP BY CUBE(i.Shelf,i.LocationID)

    2.使用ROLLUP和GROUP BY,根据GROUP BY子句中列的次序增加分层的数据汇总:

    USE AdventureWorks go SELECT i.Shelf,p.Name,SUM(i.Quantity) Total FROM Production.ProductInventory i INNER JOIN Production.Product p ON i.ProductID=p.ProductID GROUP BY ROLLUP (i.Shelf,p.Name)

    3.使用分组集创建运算符自定义汇总。

        SQL Server 2008引入了在单个查询结果集中自定义分组集的能力,而不再是只能借助多个UNION ALL来实现。而且与前面演示的CUBE和ROLLUP操作相比,使用分组集可以更好地控制聚合内容。这一操作使用GROUPING SETS来完成。     首先,演示为查询定义示例业务需求9假设我希望得到一个包含三个不同聚合数量汇总的结果集。具体来说,我希望查看每个货架上的产品数量、每个货架上每种产品的数量以及每个地区每种产品的数量。     在SQL Scrver的早期版本中,要达到这一点必须使用UNION ALL:  

    USE AdventureWorks go SELECT NULL,i.LocationID,p.Name,SUM(i.Quantity) Total FROM Production.productInventory i INNER JOIN Production.product p ON i.ProductID=p.ProductID WHERE Shelf IN('A','C') AND Name IN('Chain','Decal','Head Tube') GROUP BY i.LocationID,p.Name UNION ALL SELECT i.Shelf,NULL,NULL,SUM(i.Quantity) Total FROM Production.ProductInventory i INNER JOIN Production.Product p ON i.ProductID=p.ProductID WHERE Shelf IN ('A','C') AND Name IN('Chain','Decal','Head Tube') GROUP BY i.Shelf SELECT i.Shelf,NULL,p.Name,SUM(i.Quantity) Total FROm Production.ProductInventory i INNER JOIN Production.product p ON i.ProductID=p.productID WHERE Shelf in('A','C') AND Name IN('Chain','Decal','Head Tube') GROUP BY i.Shelf,p.Name

        在SQL Server 2008中,可以使用GROUPING SETS操作符替代在单个结果集中定义你想要返回的各种聚合运算,从而节省额外的代码。

    SELECT i.Shelf,i.LocationID,p.Name,SUM(i.Quantity) Total FROM Production.ProductInventory i INNER JOIN Production.Product p ON i.ProductID=p.ProductID WHERE Shelf IN('A','C') AND Name IN('Chain','Decal','Head Tube') GROUP BY GROUPING SETS((i.Shelf),(i.Shelf,p.Name),(i.LocationID,p.Name))

    4.展现GROUPING生成的行

       在前面的技巧中,进行分组的那些行在没有参与聚合总和的列中有NULL值。例如,当为货架C生成总和时,地区和产品名称列为NULL:

        如果数据中确定不包含NULL,那么NULL值足可接受的;但是,如果存在NULL值呢?如何区分出那些‘“存储的”NULL和由ROLLUP、CUBE和GROUPING SETS生成的NULL呢?     为了确定这个问题,可以使用GROUPING和GROUPING_ ID函数。我会在这个技巧中讨论GROUPING,然后在下一个技巧中讨论GROUPING_ID。在SQL Server的早期版本中,GROUPING是可用的,它可以简单地评估一行是否为聚合的产物口例如,下面的查询使用CASE语句来评估行是否为根据货架统计的总和、根据地区统计的总和、全部合计或是通常的非cube的行:

    USE AdventureWorks go SELECT i.Shelf,i.LocationID, CASE WHEN GROUPING(i.Shelf)=0 AND GROUPING(i.LocationID)=1 THEN 'Shelf Total' WHEN GROUPING(i.Shelf)=1 AND GROUPING(i.LocationID)=0 THEN 'Location Total' WHEN GROUPING(i.Shelf)=1 AND GROUPING(i.LocationID)=1 THEN 'Grand Total' ELSE 'Regular Row' END RowType,SUM(i.Quantity) Total FROM Production.productInventory i WHERE LocationID=2 GROUP BY CUBE(i.Shelf,i.LocationID)

    5.使用GROUPING_ID标识分组级别

        随着增加到GROUP BY的新列和可分组与聚合的唯一数据值,标识出哪些行属于哪一种聚合变得更加困难。例如,假设有一个非聚合报表,显示了地区为3和箱柜为1和2的产品数量:

    USE AdventureWorks go SELECT i.Shelf,i.LocationID,i.Bin,i.Quantity FROM Production.ProductInventory i WHERE i.LocationID IN(3) AND i.Bin IN(1,2)

        现在如果希望生成基于货架、地区和箱柜的各种组合的聚合报表,可以使用CUBE产生所有这些潜在组合的汇总:

    SELECT i.Shelf,i.LocationID,i.Bin,SUM(i.Quantity) Total FROM Production.ProductInventory i WHERE i.LocationID IN(3) AND i.Bin IN(1,2) GROUP BY CUBE(i.Shelf,i.LocationID,i.Bin) ORDER BY i.Shelf,i.LocationID,i.Bin

    尽管查询返同了CUBE期望的各种聚合,但结果仍然是难以理解的:

        这时GROUPING ID就派上用场了。使用这个函数,可以确定行的分组级别。这个函数比GROUPING更加复杂,这是因为GROUPING_ID用一个或多个列作为输入,然后返回列的二迸制数字计算结果对应的整数。     这可以通过示例进行最好的描述,因此我将使用前面的查询,并增加CASE逻辑来返回合适的行描述符:

    USE AdventureWorks go SELECT i.Shelf,i.LocationID,i.Bin, CASE GROUPING_ID(i.Shelf,i.LocationID,i.BIN) WHEN 1 THEN 'Shelf/Location Total' WHEN 2 THEN 'Shelf/Bin Total' WHEN 3 THEN 'Shelf/Total' WHEN 4 THEN 'Location/Bin Total' WHEN 5 THEN 'Location Total' WHEN 6 THEN 'Bin Total' WHEN 7 THEN 'Grand Total' ELSE 'Regular Row' END,SUM(i.Quantity) Total FROM Production.ProductInventory i WHERE i.LocationID IN(3) AND i.Bin IN(1,2) GROUP BY CUBE(i.Shelf,i.LocationID,i.Bin) ORDER BY i.Shelf,i.LocationID,i.Bin

     

    Processed: 0.040, SQL: 9