【问题标题】:Pivot and Unpivot for 4 joined table SQL Server4 个连接表 SQL Server 的透视和反透视
【发布时间】:2016-02-04 04:37:36
【问题描述】:

我使用的是 SQL Server 2012,我想创建一个包含 4 个连接表的数据透视表。

这是我的查询:

SELECT 
    a.Itemno, a.Qty as PlanMilling, 
    ISNULL(b.MinimStock, 0) as MinStock, 
    CAST(a.ScheduleDate as Date) AS Schedule, 
    ISNULL(SUM(c.Qty), 0) as QtyBuilding,
    ISNULL(d.RunQty, 0) as QtyStock, 
    d.itemcode, 
    ISNULL((a.Qty + d.RunQty) - SUM(c.Qty), 0) as Balance
FROM 
    Schedule a 
LEFT OUTER JOIN 
    Item b ON a.ItemNo = b.ItemNo
LEFT OUTER JOIN 
    ShopOrderList c on a.ItemNo = c.ItemNo and a.ScheduleDate = c.ScheduleDate
LEFT OUTER JOIN  
    (SELECT  
         RunQty, ItemCode  
     FROM
         ICMutTran a
     INNER JOIN
         (SELECT 
              itemcode as ItemNo, max(id) as maxid 
          FROM
              ICMutTran 
          GROUP BY 
              itemcode) AS b ON a.id = b.maxid) d ON (a.ItemNo = d.ItemCode)
GROUP BY 
    a.ItemNo, a.Qty, b.MinimStock, a.ScheduleDate, d.RunQty, d.itemcode

结果:

ItemNo   |   PlanMilling   |   MinStock   |   Schedule   |   QtyBuilding   |   QtyStock   |   ItemCode   |
----------------------------------------------------------------------------------------------------------
123      |   1000          | 100          | 2016-02-04   | 200             | 1500         | 123          |
123      |   2000          | 100          | 2016-02-05   | 100             | 1500         | 123          |
123      |   1500          | 100          | 2016-02-06   | 150             | 1500         | 123          |

我需要的是这个:

ColName     |   2016-02-04   |   2016-02-05   |   2016-02-06   |
----------------------------------------------------------------
PlanMilling |   1000         |   2000         |   1500         |
MinStock    |    100         |    100         |    100         |
QtyBuilding |    200         |    100         |    150         |
QtyStock    |   1500         |   1500         |   1500         |

谁能解决我的问题?我真的需要你的帮助(对不起我的英语不好)..

谢谢

【问题讨论】:

    标签: sql-server tsql pivot unpivot


    【解决方案1】:

    这会在 ScheduleDate 上动态执行您的 PIVOT。您可以通过将 SELECT 语句重写为

    来使用此脚本
    SELECT <your selects> INTO #tt FROM <the rest of your query>
    

    并使用CREATE TABLE #ttINSERT INTO #tt 语句之后的脚本部分。旋转后不要忘记 DROP 临时表。

    CREATE TABLE #tt(ItemNo INT,PlanMilling INT,MinStock INT,Schedule VARCHAR(10),QtyBuilding INT,QtyStock INT,ItemCode INT);
    INSERT INTO #tt(ItemNo,PlanMilling,MinStock,Schedule,QtyBuilding,QtyStock,ItemCode)VALUES
        (123,1000,100,'2016-02-04',200,1500,123),
        (123,2000,100,'2016-02-05',100,1500,123),
        (123,1500,100,'2016-02-06',150,1500,123);
    
    DECLARE @schedule_dates NVARCHAR(MAX)=STUFF((
        SELECT DISTINCT
            ','+QUOTENAME(Schedule)
        FROM
            #tt
        FOR
            XML PATH('')
        ),1,1,''
    );
    
    DECLARE @stmt NVARCHAR(MAX)=N'
        SELECT
            ColName,' +
            @schedule_dates+'
        FROM
            #tt
            UNPIVOT (
                value 
                FOR ColName in (PlanMilling,MinStock,QtyBuilding,QtyStock)
            ) AS up
            PIVOT (
                MAX(value) 
                FOR Schedule IN ('+@schedule_dates+')
            ) AS p;
    ';
    EXECUTE sp_executesql @stmt;
    
    DROP TABLE #tt;
    

    结果:

    +-------------+------------+------------+------------+
    |   ColName   | 2016-02-04 | 2016-02-05 | 2016-02-06 |
    +-------------+------------+------------+------------+
    | MinStock    |        100 |        100 |        100 |
    | PlanMilling |       1000 |       2000 |       1500 |
    | QtyBuilding |        200 |        100 |        150 |
    | QtyStock    |       1500 |       1500 |       1500 |
    +-------------+------------+------------+------------+
    

    【讨论】:

    • 这真的很有帮助,谢谢!但是,当我放入存储过程时有一个小问题,当我执行存储过程时没有结果
    • @Jackques 你好 Jackques。我很遗憾听到。你现在要做的是首先承认我通过接受这个答案解决了你在问题中描述的问题。你的问题没有提到存储过程,所以现在不可能改变我对你在评论中提出的问题的回答。这不是在 StackOverflow 上做事的方式。如果你一直遇到这个问题,现在最好的办法是在 StackOverflow 上提出一个新问题,详细说明你遇到的新问题(即从存储过程运行时你没有得到输出)。
    • @Jackques 当您提出这个新问题时,请返回此答案并给我评论,以便我找到您的新问题。如果没有人回答你的新问题,我会看看。
    • @Jackques 只是为了运动,我将此解决方案包装在一个存储过程中并执行它。这与简单地运行此脚本返回的结果相同。所以最好你问一个新问题,尽可能详细说明你尝试了什么。如果您接受此答案,我将努力确保您在存储过程中运行的问题得到解决。 GL!
    • 抱歉 TT.,这只是我对存储过程的小错误,您的查询非常好地解决了我的问题,真的很有帮助!非常感谢!
    【解决方案2】:

    这是一个使用union allconditional aggregation 的选项(虽然有点难看):

    with cte as (
        <<your query here>>
    )
    select 'PlanMilling' ColName,
           max(case when Schedule = '2016-02-04' then PlanMilling end) '2016-02-04',
           max(case when Schedule = '2016-02-05' then PlanMilling end) '2016-02-05',
           max(case when Schedule = '2016-02-06' then PlanMilling end) '2016-02-06'
    from cte
    union all
    select 'MinStock' ColName,
           max(case when Schedule = '2016-02-04' then MinStock end) '2016-02-04',
           max(case when Schedule = '2016-02-05' then MinStock end) '2016-02-05',
           max(case when Schedule = '2016-02-06' then MinStock end) '2016-02-06'
    from cte
    union all
    select 'QtyBuilding' ColName,
           max(case when Schedule = '2016-02-04' then QtyBuilding end) '2016-02-04',
           max(case when Schedule = '2016-02-05' then QtyBuilding end) '2016-02-05',
           max(case when Schedule = '2016-02-06' then QtyBuilding end) '2016-02-06'
    from cte
    union all
    select 'QtyStock' ColName,
           max(case when Schedule = '2016-02-04' then QtyStock end) '2016-02-04',
           max(case when Schedule = '2016-02-05' then QtyStock end) '2016-02-05',
           max(case when Schedule = '2016-02-06' then QtyStock end) '2016-02-06'
    from cte
    

    【讨论】:

    • 我想用动态时间表创建一个支点
    • @Jackques -- 如果是这种情况,您需要考虑使用 dynamic sql 进行旋转。 SO上的几个例子。
    • 你能把这些链接分享给我吗?拜托,我真的很想解决这个问题,即使它只是一个语法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 2016-06-29
    • 1970-01-01
    相关资源
    最近更新 更多