表字段及记录如下:Id  Type  Value
1   T1    120.00
2   T1     78.00
3   T2     88.00
4   T2    103.00
......求SQL语句形成明细列表及分项汇总如下:-----------------------
Type  Value
T1    120.00
T1     78.00
ST    198.00 (这里ST表示 SubTotal)
T2     88.00
T2    103.00
ST    192.00

解决方案 »

  1.   

    -- 2005
    SELECT i.Shelf, SUM(i.Quantity) Total
      FROM Production.ProductInventory i
     GROUP BY i.Shelf with cube;-- 2008 
    SELECT i.Shelf, SUM(i.Quantity) Total
      FROM Production.ProductInventory i
     GROUP BY CUBE (i.Shelf)
      

  2.   

    grouping函数和 GROUP WITH ROLLUP
      

  3.   

    select type,value from 表名你是要只显示两列,不显示id吗?
      

  4.   

    -- 2005
    SELECT i.Type, SUM(i.Value) Value
      FROM tb i
     GROUP BY i.Type with cube;-- 2008 
    SELECT i.Type, SUM(i.Value) Value
      FROM tb i
     GROUP BY CUBE (i.Type)
      

  5.   

    -- 1.9 使用APPLY来为每行调用表值函数 ( P30 )CREATE FUNCTION dbo.fn_WorkOrderRouting
      (@WorkOrderID int) RETURNS TABLE
    AS
    RETURN
      SELECT WorkOrderID,
     ProductID,
     OperationSequence,
     LocationID
    FROM Production.WorkOrderRouting
       WHERE WorkOrderID = @WorkOrderID
    GOSELECT w.WorkOrderID,
       w.OrderQty,
       r.OperationSequence
      FROM Production.WorkOrder w
    CROSS APPLY dbo.fn_WorkOrderRouting
    (w.WorkOrderID) AS r
    ORDER BY w.WorkOrderID, w.OrderQty, r.ProductID;-- 1.10.2 使用 PIVOT 把单列值转化为多列和聚合数据
    -- PIVOT 运算符能让我们创建交叉表的查询,它把值转化为多列,使用聚合来根据新列对数据进行分组。FROM table_source
    PIVOT  ( aggregate_function ( value_column )
    FOR pivot_column
    IN ( <column_list> )
      ) table_alias---------------------------------------------------------------------------------
    |                             表1-3      PIVOT 参数                             |
    ---------------------------------------------------------------------------------
    |          参            数          |          描                  述          |
    ---------------------------------------------------------------------------------
    | table_source                       | 要旋转数据的表                           |
    ---------------------------------------------------------------------------------
    | aggregate_function(value_column)   | 要在某列上使用的集合函数                 |
    ---------------------------------------------------------------------------------
    | pivot_column                       | 用于创建列头的列                         |
    ---------------------------------------------------------------------------------
    | column_list                        | 要从旋转列中旋转的值                     |
    ---------------------------------------------------------------------------------
    | table_alias                        | 旋转结果集的表别名                       |
    ----------------------------------------------------------------------------------- 下一个示例演示如何实现类似微软Excel旋转表特性的PIVOT和聚合数据功能:把一列中的值转到多列,在结果中显示聚合数据。-- 示例的第一部分显示旋转之前的数据。查询结果显示了雇员的轮换和他们所在的部门:SELECT s.Name ShiftName,
           h.BusinessEntityID,
           d.Name DepartmentName
      FROM HumanResources.EmployeeDepartmentHistory h
      INNER JOIN HumanResources.Department d ON
    h.DepartmentID = d.DepartmentID
      INNER JOIN HumanResources.Shift s ON
            h.ShiftID = s.ShiftID
      WHERE EndDate IS NULL AND
            d.Name IN ('Production','Engineering','Marketing')
      ORDER BY ShiftName;
    -- 1.10.3 使用 UNPIVOT 规范化数据  ( P36) 
    CREATE TABLE dbo.Contact
      (EmployeeID int NOT NULL,
       PhoneNumber1 bigint,
       PhoneNumber2 bigint,
       PhoneNUmber3 bigint)
    GOINSERT dbo.Contact
    (EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3)
    VALUES(1,2718353831,3385531980,5324571342)INSERT dbo.Contact
    (EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3)
    VALUES(2,6007163571,6875099415,7756620787)INSERT dbo.Contact
    (EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3)
    VALUES(3,9439250939,NULL,NULL)SELECT EmployeeID, PhoneType, PhoneValue
      FROM
    (SELECT EmployeeID, PhoneNumber1, PhoneNumber2, PhoneNumber3
       FROM dbo.Contact) c
     UNPIVOT
        (PhoneValue FOR PhoneType IN ([PhoneNumber1], [PhoneNumber2], [PhoneNumber3])
    ) AS p;
    -- 1.10.4 使用 EXCEPT 和 INTERSECT 返回不重复的或匹配的行 ( 38 )
    -- 使用 INTERSECT 和 EXCEPT 运算符,可以返回只存在于左查询中的不重复行 (使用EXCEPT),或者同时存在于左右两个查询中的不重复行 (使用INTERSECT)。-- INTERSECT 和 EXCEPT 在数据集比较时很有用。例如,如果你需要比较测试表和正式表中的行,
    -- 可以使用EXCEPT轻松找到和获取那些在一个表中存在而在另一个表中不存在的行。这些操作数在数据恢复的时候同样有用,因为你可以从过去的数据库中恢复丢失的数据,
    -- 先和当前正式表中的数据进行比较,然后恢复相应的被删除的行。-- 在这个示例中,我们创建了演示表,它包含了Production.Product表中的部分数据:-- 先创建两个基于Production.Product的表,用于演示EXCEPT和INTERSECT
    -- 更多有关 ROW_NUMBER 的信息参阅第8章-- 创建 TableA
    SELECT prod.ProductID, prod.Name
    INTO dbo.TableA
    FROM
    (SELECT ProductID, Name, ROW_NUMBER() OVER (ORDER BY ProductID) RowNum
    FROM Production.Product) prod
    WHERE RowNum BETWEEN 1 and 20;-- 创建 TableB
    SELECT prod.ProductID, prod.Name
    INTO dbo.TableB
    FROM
    (SELECT ProductID, Name, ROW_NUMBER() OVER (ORDER BY ProductID) RowNum
    FROM Production.Product) prod
    WHERE RowNum BETWEEN 10 and 19;SELECT ProductID, Name
      FROM dbo.TableA
    EXCEPT
    SELECT ProductID, Name
      FROM dbo.TableB;-- 要想在两个结果中都能找到的不重复值,可以使用 INTERSECT 运算符:SELECT ProductID, Name
      FROM dbo.TableA
    INTERSECT
    SELECT ProductID, Name
      FROM dbo.TableB;-- 1.11 汇总数据 ( P40 )
    -- 在之后的3个技巧中,我会演示如何使用下面的运算符来汇总结果集中的数据:
    -- *1) 使用 CUBE 根据 GROUP BY 子句的列来为结果庥增加汇总值;
    -- *2) 使用 ROLLUP 和 GROUP BY,根据 GROUP BY子句中列的次序增加分层的数据汇总;
    -- *3) 使用 GROUPING SETS 运算符在一个结果集中进行自定义聚合,而不需要使用 UNION ALL。-- 2005
    SELECT i.Shelf, SUM(i.Quantity) Total
      FROM Production.ProductInventory i
     GROUP BY i.Shelf with cube;-- 2008 
    SELECT i.Shelf, SUM(i.Quantity) Total
      FROM Production.ProductInventory i
     GROUP BY CUBE (i.Shelf)-- 2005
    SELECT i.Shelf, i.LocationID, SUM(i.Quantity) Total
      FROM Production.ProductInventory i
     GROUP BY i.Shelf, i.LocationID with cube;-- 2008
    SELECT i.Shelf, i.LocationID, SUM(i.Quantity) Total
      FROM Production.ProductInventory i
     GROUP BY CUBE (i.Shelf, i.LocationID );-- 1.11.2 使用 ROLLUP 来汇总数据
    -- GROUP BY ROLLUP 用来根据 GROUP BY 子句中的列的次序来增加层次化的数据汇总。-- 这个示例获取了货架、产品名和产品的总数:-- 2005
    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 i.Shelf, p.Name WITH ROLLUP;-- 2008
    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);-- 1.11.3 使用分组集创建自定义汇总
    -- SQL Server 2008 引入了在单个查询结果集中自定义分组集的能力,而不再是只能借助多个 UNION ALL 来实现。而且与前面演示的 CUBE 和 ROLLUP 相比,
    -- 使用分组集可以更好地控制聚合内容。这一操作使用 GROUPING SETS 来完成。-- 首先,我会演示为查询定义示例业务需求。假设我希望得到一个包含三个不同聚合数量汇总的结果集。具体来说,我希望查看每个货架上的产品数量、
    -- 每个货架上每种产品的数量以及每个地区每种产品的数量。-- 在 SQL Server的早期版本中,要达到这一点必须使用 UNION ALL:-- 2005
    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
    UNION ALL
    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;
      

  6.   

    如果是每种type的汇总,用group by就可以实现了!!
      

  7.   

    -- 在 SQL Server 2008 中,可以使用 GROUPING SETS 操作符替代在单个结果集中定义你想要返回的各种聚合运算符,从而节省额外代码。-- 2008
    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));-- 1.11.4 展现 GROUPING 生成的行 ( P44 )
    -- 你可能会注意到,在前面的技巧中,进行分组的那些行在没有参与聚合总和的列中有 NULL 值。例如,当为货架C生成总和时,地区产品名称列为 NULL:-- 如果数据中确定不包含 NULL,那么 NULL 值是可接受的;但是,如果存在 NULL 值呢?如何区分出那些“存储的” NULL 和
    -- 由 ROLLUP、CUBE 和 GROUPING SETS 生成的 NULL 呢?-- 为了确定这个问题,可以使用 GROUPING_ID。在SQL Server的早期版本中,GROUPING是可用的,它可以简单地评估一行是否为聚合的产物。例如,
    -- 下面的查询使用 CASE 语句来评估行是否为根据货架统计的总和、根据地区统计的总和、全部合计或是通常的非 cube 的行:
    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)-- 解析
    -- GROUPING 函数允许你区分并操作那些使用 CUBE、ROLLUP 和 GROUPING SETS聚合自动生成的行。在这个示例中,先用平常的SELECT语句,
    -- 该语句包含了Shelf和Location列:
    SELECT
      i.Shelf,
      i.LocationID,-- 在这之后,是一个CASE语句,用来计算GROUPING 语句的返回值并合并。-- 如果 GROUPING 返回的值为1(真),表示NULL不是实际的数据值,而是聚合操作的结果,可以理解为值“全部”。因此在示例中,如果由于CUBE聚合过程而不是数据本身,
    -- 造成货架的值不为NULL但地区ID为NULL,则返回字符串Shelf Total:......-- 1.11.5 使用 GROUPING_ID 标识分组级别
    -- 随着增加到 GROUP BY 的新列和可分组与聚合的唯一数据值,标识出哪些行属于哪一种聚合变得更加困难。
    -- 例如,假设我有一个非聚合报表,显示了地区为3和箱柜为1和2的产品数量:
    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逻辑来返回合适的行描述符:
    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.BinSelf Loc Bin
    0 0 1
    0 1 0
    0 1 1
    1 0 0
    1 0 1
    1 1 0
    1 1 1......-- 1.12 公共表达式 ( P49 )
    -- 公共表达式 (CTE) 和视图或衍生查询相似,允许创建一个临时的查询,该查询能在SELECT、INSERT、UPDATE或DELETE查询范围中引用。
    -- 和衍生查询不同,不需要在每次使用CTE的时候复制查询定义多次。同时也能在CTE定义中使用局部变量----这是在视图定义中所不能做到的。CTE 的基本语法如下:WITH expression_name [ ( column_name [,...n] ) ]
    AS ( CTE_query_definition )-- 表1-4描述了CTE的参数。---------------------------------------------------------------------------------
    |                             表1-4        CTE 参数                             |
    ---------------------------------------------------------------------------------
    |          参            数          |          描                  述          |
    ---------------------------------------------------------------------------------
    | expression_name                    | 公共表达式的名字                         |
    ---------------------------------------------------------------------------------
    | column_name [,...n]                | 表达式的唯一列名                         |
    ---------------------------------------------------------------------------------
    | CTE_query_definition               | 定义公共表达式的SELECT查询               |
    ----------------------------------------------------------------------------------- 非递归的CTE在查询中不引用自己。它就像查询的临时结果集。递归的CTE的定义和非递归的CTE差不多,只是递归的CTE返回层次化的以及和自身相关的数据。
    -- 和其他方式相比,使用CTE来表示递归数据能尽量减少需要的代码量。-- 接下来的两个技巧会演示非递归的和递归的CTE。-- 1.12.1 使用非递归的公共表表达式 ( P49 )
    -- 这个公共表达式的示例演示返回Purchasing.Vendor表中的供应商----返回根据名字排序的前5个和最后5个结果:
    WITH VendorSearch (RowNumber, VendorName, AccountNumber)
    AS
    (
    SELECT ROW_NUMBER() OVER (ORDER BY Name) RowNum,
           Name,
           AccountNumber
    FROM Purchasing.Vendor
    )SELECT RowNumber,
           VendorName,
           AccountNumber
    FROM VendorSearch
    WHERE RowNumber BETWEEN 1 AND 5
    UNION
    SELECT RowNumber,
           VendorName,
           AccountNumber
    FROM VendorSearch
    WHERE RowNumber BETWEEN 100 AND 104-- 前面的示例使用了UNION,但是非递归的CTE也能像其他SELECT查询那样使用:
    WITH VendorSearch (VendorID,VendorName)
    AS
    (
    SELECT VendorID,
           Name
    FROM Purchasing.Vendor
    )SELECT v.VendorID,
           v.VendorName,
           p.ProductID,
           p.StandardPrice
    FROM VendorSearch v
    INNER JOIN Purchasing.ProductVendor p ON
      v.VendorID = p.VendorID
    ORDER BY v.VendorName-- 警告 如果CTE是一批语句的一部分,那么CTE定义之前的语句必须以分号结尾。-- 注意 可以使用分号作为 SQL Server 语句的终止符。多数情况下这样做不是必需的,但是符合ANSI标准,你可以在一些微软的文件中看到这样的使用。-- 1.12.2 使用递归的公共表达式 ( P52 )
    -- 在这个示例中,新的Company 表定义了一个假想的巨大的联合企业。每一个公司都有一个CompanyID和可选的ParentCompanyID。
    -- 这个示例会演示如何使用递归CTE在结果中显示公司的层次。首先,创建表:
    CREATE TABLE dbo.Company
      (CompanyID int NOT NULL PRIMARY KEY,
       ParentCompanyID int NULL,
       CompanyName varchar(25) NOT NULL)-- 接着,向新表中插入行(使用SQL Server 2008新语法的方式将在第2章中演示):
    INSERT dbo.Company (CompanyID, ParentCompanyID, CompanyName)
    VALUES
      (1,NULL,'Mega-Corp'),
      (2,1,'Mediamus-Corp'),
      (3,1,'KindaBigus-Corp'),
      (4,3,'GettinSmaller-Corp'),
      (5,4,'Smallest-Corp'),
      (6,5,'Puny-Corp'),
      (7,5,'Small2-Corp')-- 现在就是实际例子:
    WITH CompanyTree(ParentCompanyID,CompanyID,CompanyName,CompanyLevel)
    AS
    (
      SELECT ParentCompanyID,
        CompanyID,
        CompanyName,
        0 AS CompanyLevel
      FROM dbo.Company
      WHERE ParentCompanyID IS NULL
      UNION ALL
      SELECT c.ParentCompanyID,
        c.CompanyID,
        c.CompanyName,
        p.CompanyLevel + 1
      FROM dbo.Company c
        INNER JOIN CompanyTree p
        ON c.ParentCompanyID = p.CompanyID
    )
    SELECT ParentCompanyID, CompanyID, CompanyName, CompanyLevel
    FROM CompanyTree......-- 然而,使用这种有用的新特性需要小心。如果你没有正确地创建递归CTE,可能会产生无限循环。
    -- 在测试的时候,要避免无限循环,可以使用本章前面提到的MAXRECURSION提示。-- 例如,如果希望阻止前面的示例超过2级,只需要在查询最后添加具有MAXRECURSION的OPTION子句:
    WITH CompanyTree(ParentCompanyID, CompanyID, CompanyName, CompanyLevel) AS
    (
      SELECT ParentCompanyID,CompanyID,CompanyName, 0 AS CompanyLevel
      FROM dbo.Company
      WHERE ParentCompanyID IS NULL
      UNION ALL
      SELECT c.ParentCompanyID, c.CompanyID, c.CompanyName, p.CompanyLevel + 1
      FROM dbo.Company c
        INNER JOIN CompanyTree p
        ON c.ParentCompanyID = p.CompanyID
    )
    SELECT ParentCompanyID, CompanyID, CompanyName, CompanyLevel
    FROM CompanyTree
    OPTION (MAXRECURSION 2)
      

  8.   


    --> 数据库版本:
    --> Microsoft SQL Server 2008 (RTM) - 10.0.1600.22
    --> 测试数据:[TB]
    IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[TB]') 
    AND type in (N'U')) --U 代表你查询的是表
    DROP TABLE [TB]
    GO---->建表
    create table [TB]([Id] int,[Type] varchar(2),[Value] numeric(5,2))
    insert [TB]
    select 1,'T1',120.00 union all
    select 2,'T1',78.00 union all
    select 3,'T2',88.00 union all
    select 4,'T2',103.00
    GO--> 查询结果
    select [Type],Value  from TB
    union 
    SELECT isnull([Type],'ST'), sum(Value) 
    FROM [TB]
    group by [Type]  
    with rollup
     
    --> 删除表格
    --DROP TABLE [TB]