如何在多列上转动?

时间:2017-11-16 07:34:45

标签: sql sql-server pivot sql-server-2014

我正在尝试使用多个列,我正在使用SQL Server 2014,但是,我无法弄清楚如何做到这一点。这是我到目前为止所尝试的内容:

DECLARE @Table TABLE (
    Name NVARCHAR(MAX),
    TypeId INT,
    TotalOrders INT,
    GrandTotal MONEY
)

INSERT INTO @Table
    (Name, TypeId, TotalOrders, GrandTotal)
VALUES
    ('This Month', 1, 10, 1),
    ('This Month', 2, 5, 7),
    ('This Week', 1, 8, 3),
    ('Last Week', 1, 8, 12),
    ('Yesterday', 1, 10, 1),
    ('Yesterday', 2, 1, 5)

产生以下结果:

Name                             TypeId      TotalOrders GrandTotal
-------------------------------- ----------- ----------- ---------------------
This Month                       1           10          1.00
This Month                       2           5           7.00
This Week                        1           8           3.00
Last Week                        1           8           12.00
Yesterday                        1           10          1.00
Yesterday                        2           1           5.00

要将这些行放入列中,我试过这个:

SELECT
    TypeId,
    ISNULL([Yesterday], 0) AS YesterdayTotalOrders,
    ISNULL([This Week], 0) AS ThisWeekTotalOrders,
    ISNULL([Last Week], 0) AS LastWeekTotalOrders,
    ISNULL([This Month], 0) AS ThisMonthTotalOrders
FROM
    (SELECT Name, TypeId, TotalOrders FROM @Table) AS src
PIVOT (
    SUM(TotalOrders) FOR Name IN (
        [Yesterday],
        [This Week],
        [Last Week],
        [This Month]
    )
) AS p1

产生以下结果集:

TypeId      YesterdayTotalOrders ThisWeekTotalOrders LastWeekTotalOrders ThisMonthTotalOrders
----------- -------------------- ------------------- ------------------- --------------------
1           10                   8                   8                   10
2           1                    0                   0                   5

现在,我需要为GrandTotal添加其他几列,例如YesterdayGrandTotalThisWeekGrandTotal等等,但我无法弄清楚如何实现这一目标。

任何帮助都将受到高度赞赏。

更新#1:这是预期的结果集:

TypeId      YesterdayTotalOrders ThisWeekTotalOrders LastWeekTotalOrders ThisMonthTotalOrders YesterdayGrandTotal   ThisWeekGrandTotal    LastWeekGrandTotal    ThisMonthGrandTotal
----------- -------------------- ------------------- ------------------- -------------------- --------------------- --------------------- --------------------- ---------------------
1           10                   8                   8                   10                   1.00                  3.00                  12.00                 1.00
2           1                    0                   0                   5                    5.00                  0.00                  0.00                  7.00

3 个答案:

答案 0 :(得分:1)

条件聚合可能是一个解决方案:

select typeID,
    SUM(case when name = 'Yesterday' then totalOrders else 0 end) as YesterdayTotalOrders,
    SUM(case when name = 'This Week' then totalOrders else 0 end) as ThisWeekTotalOrders,
    SUM(case when name = 'Last Week' then totalOrders else 0 end) as LastWeekTotalOrders,
    SUM(case when name = 'This Month' then totalOrders else 0 end) as ThisMonthTotalOrders,
    SUM(case when name = 'Yesterday' then GrandTotal else 0 end) as YesterdayGrandTotal,
    SUM(case when name = 'This Week' then GrandTotal else 0 end) as ThisWeekGrandTotal,
    SUM(case when name = 'Last Week' then GrandTotal else 0 end) as LastWeekGrandTotal,
    SUM(case when name = 'This Month' then GrandTotal else 0 end) as ThisMonthGrandTotal    
from @table
group by typeID

或者,您可以像这样使用CROSS APPLYPIVOT

SELECT
    TypeId,
    ISNULL([Yesterday], 0) AS YesterdayTotalOrders,
    ISNULL([This Week], 0) AS ThisWeekTotalOrders,
    ISNULL([Last Week], 0) AS LastWeekTotalOrders,
    ISNULL([This Month], 0) AS ThisMonthTotalOrders,
    ISNULL([grant Yesterday], 0) AS YesterdayGrandTotal,
    ISNULL([grant This Week], 0) AS ThisWeekGrandTotal,
    ISNULL([grant Last Week], 0) AS LastWeekGrandTotal,
    ISNULL([grant This Month], 0) AS ThisMonthGrandTotal
FROM
    (
      SELECT t.* 
      FROM @Table
      CROSS APPLY (values(Name, TypeId, TotalOrders),
                     ('grant ' + Name, TypeId, GrandTotal)) 
                     t(Name, TypeId, TotalOrders)
    ) AS src
PIVOT (
    SUM(TotalOrders) FOR Name IN (
        [Yesterday],
        [This Week],
        [Last Week],
        [This Month],
        [grant Yesterday],
        [grant This Week],
        [grant Last Week],
        [grant This Month]
    )
) AS p1

demo

两种解决方案都只扫描输入表一次,它们的查询计划非常相似。两种解决方案都优于两个枢轴JOIN(我最初提供的解决方案),因为两个枢轴需要扫描输入表两次。

答案 1 :(得分:1)

您也可以将pivots P1 TotalOrdersP2分开来使用GrandTotal;WITH CTE AS ( SELECT P1.TypeId, ISNULL(P1.[Yesterday], 0) AS YesterdayTotalOrders, ISNULL(P1.[This Week], 0) AS ThisWeekTotalOrders, ISNULL(P1.[Last Week], 0) AS LastWeekTotalOrders, ISNULL(P1.[This Month], 0) AS ThisMonthTotalOrders FROM (SELECT Name, TypeId, TotalOrders FROM @Table) AS src PIVOT (SUM(TotalOrders) FOR src.Name IN ( [Yesterday], [This Week], [Last Week], [This Month])) AS P1 ), CTE1 AS ( SELECT P1.TypeId, ISNULL(P1.[Yesterday], 0) AS YesterdayGrandTotal, ISNULL(P1.[This Week], 0) AS ThisWeekTGrandTotal, ISNULL(P1.[Last Week], 0) AS LastWeekGrandTotal, ISNULL(P1.[This Month], 0) AS ThisMonthGrandTotal FROM (SELECT Name, TypeId, GrandTotal FROM @Table) AS src PIVOT (SUM(GrandTotal) FOR src.Name IN ( [Yesterday], [This Week], [Last Week], [This Month])) AS P1 ) SELECT C.TypeId , C.YesterdayTotalOrders, C.ThisWeekTotalOrders, C.LastWeekTotalOrders, C.ThisMonthTotalOrders , C1.YesterdayGrandTotal , C1.ThisWeekTGrandTotal ,C1.LastWeekGrandTotal , C1.ThisMonthGrandTotal FROM CTE C INNER JOIN CTE1 C1 ON C1.TypeId = C.TypeId

TypeId YesterdayTotalOrders ThisWeekTotalOrders LastWeekTotalOrders ThisMonthTotalOrders YesterdayGrandTotal ThisWeekGrandTotal LastWeekGrandTotal ThisMonthGrandTotal ----------- -------------------- ------------------- ------------------- -------------------- --------------------- --------------------- --------------------- --------------------- 1 10 8 8 10 1.00 3.00 12.00 1.00 2 1 0 0 5 5.00 0.00 0.00 7.00
public enum ValidityTypes : int
{
    [Description("Not Set")]
    None = 0,
    [Description("Zero Validity")]
    ZeroValidity = 1,
    [Description("Life Time Validity")]
    LifeTimeValidity = 2,
    [Description("N Months")]
    NMonths = 3,
    [Description("Rehire Validity in Months")]
    RehireValidity = 4
}

结果:

public ValidityTypes ValidityType { get; set; }

答案 2 :(得分:0)

在oracle我会做类似的东西。它适用于我

select * from (
SELECT   Name, TypeId,TotalOrders
--hier
,GrandTotal 
FROM test_b )
PIVOT (  SUM(TotalOrders)TotalOrders, 
--hier
SUM(grandtotal) grandtotal FOR Name IN 
('Yesterday'Yesterday,'This Week'ThisWeek,'Last Week'LastWeek,'This 
Month'ThisMonth )
) ;

所以在sql server中尝试这个

SELECT *
   /* TypeId,
    ISNULL([Yesterday], 0) AS YesterdayTotalOrders,
    ISNULL([This Week], 0) AS ThisWeekTotalOrders,
   ISNULL([Last Week], 0) AS LastWeekTotalOrders,
   ISNULL([This Month], 0) AS ThisMonthTotalOrders*/
FROM
   (SELECT Name, TypeId, TotalOrders
   ,grandtotal 
  FROM @Table) AS src
PIVOT (
    SUM(TotalOrders)TotalOrders, SUM(grandtotal)grandtotal FOR Name IN (
    [Yesterday]Yesterday,
    [This Week]ThisWeek,
    [Last Week]LastWeek,
    [This Month]ThisMonth
   )
 ) AS p1