根据两列值添加日期并转置其他列

问题描述 投票:0回答:1

我有接下来的两张桌子:

表A

产品 植物 生产周1 ... 生产周11
10011 ABC32 6742 ... 3645
10011 DEF10 3579 ... 8761
45891 GHI22 8945 ... 1556

表B

产品 植物 销售周1 ... 销售周 11
10011 ABC32 425 ... 364
10011 DEF10 879 ... 501
45891 GHI22 904 ... 395

我想要一个这样的表格,第一周从 01/01/2001 开始,第二周是 08/01/2001 依此类推,它可以是任何日期,重要的是日期之间的差异一周:

产品 植物 生产 销售 日期
10011 ABC32 6742 425 2001年1月1日
10011 ABC32 ... ... ...
10011 ABC32 3645 364 2001年6月18日
10011 DEF10 3579 879 2001年1月1日
10011 DEF10 ... ... ...
10011 DEF10 8761 501 2001年6月18日
45891 GHI22 8945 904 2001年1月1日
45891 GHI22 ... ... ...
45891 GHI22 1556 395 2001年6月18日

我尝试下一个代码来调换两列的列:

CREATE TABLE TABLE_A1 AS (SELECT P.PRODUCT AS PRODUCT_1, 
                              P.PLANT AS PLANT_1, 
                              P.PRODUCTION AS PRODUCTION_1
                              FROM (SELECT PRODUCT, PLANT, ProductionWeek1 FROM TableA 
                                    UNION 
                                    SELECT PRODUCT, PLANT, ProductionWeek2 FROM TableA
                                    UNION 
                                    ...
                                    SELECT PRODUCT, PLANT, ProductionWeek11 FROM TableA) p;

CREATE TABLE TABLE_B1 AS (SELECT s.PRODUCT AS PRODUCT_2, 
                              s.PLANT AS PLANT_2, 
                              s.SALES AS SALES_2
                              FROM (SELECT PRODUCT, PLANT, SalesWeek1 FROM TableB 
                                    UNION 
                                    SELECT PRODUCT, PLANT, SalesWeek2 FROM TableB
                                    UNION 
                                    ...
                                    SELECT PRODUCT, PLANT, SalesWeek11 FROM TableB) s;

然后尝试将所有内容放在一起

CREATE TABLE FINAL_TABLE AS ( 
                            SELECT PRODUCT_1 AS PRODUCT,
                            PLANT_1_CONSUMOS AS PLANT, 
                            PRODUCTION_1,
                            SALES_2
                            FROM TABLE_A1
                            INNER JOIN TABLE_B1 
                            ON TABLE_B1.PRODUCT_2=TABLE_A1.PRODUCT_1
                            );

但是我有一张这样的桌子:

产品 植物 生产 销售
10011 ABC32 6742 425
10011 ABC32 3645 425
10011 ABC32 3645 364

该表是无序的,因为在从 TABLE_A1 和 TABLE_B1 创建时,联合也无序,因此因此日期很重要,例如我期望这样的联合:

产品 植物 生产 销售
10011 ABC32 6742 425
10011 ABC32 ... ...
10011 ABC32 3645 364

但是我有隔壁桌

产品 植物 生产 销售
10011 ABC32 3645 364
10011 ABC32 ... ...
10011 ABC32 6742 425

上周的值在其他行中(不需要在第一行中)。有什么帮助吗?

sql date join union-all
1个回答
0
投票

当前的表格可以被描述为“透视”,因为每列都有代表一周的数据。为了理解这一点,您首先需要“逆透视”该数据,虽然您可以使用联合来执行此操作,但简单地将源表交叉连接到代表每周的一组行(即 11 行)会更有效。然后,一旦交叉连接用例表达式,即可将数据移动到所需数量的列中。例如未旋转的结果应如下所示(忽略第 2 周到第 10 周):

product plant   week    type    value
10011   ABC32   1   production  6742
10011   DEF10   1   production  3579
45891   GHI22   1   production  8945
10011   ABC32   11  production  3645
10011   DEF10   11  production  8761
45891   GHI22   11  production  1556
10011   ABC32   1   sales   425
10011   DEF10   1   sales   879
45891   GHI22   1   sales   904
10011   ABC32   11  sales   364
10011   DEF10   11  sales   501
45891   GHI22   11  sales   395

一旦以这种形式提供数据,按周生成源列的组合就是一项相对简单的任务。另请注意,在要使用的 11 周行中,也可以提供所需的日期。

nb因为您没有指定使用哪个rdbms,所以以下是Postgres语法,但除了使用的

::date
语法之外,其余的是通用SQL。

with w as (
          select 1 as week, '2001-01-01'::date as week_date union all
          /*   other weeks */
          select 11 as week, '2001-06-18'::date as week_date
        )
, unpiv as (
        select t.Product, t.Plant, w.week, w.week_date, 'production' as type
            , case
               when w.week = 1 then t.ProductionWeek1
               /* Other weeks */
               when w.week = 11 then t.ProductionWeek11
            end as value
        from Production t
        cross join w
        union all
        select t.Product, t.Plant, w.week, w.week_dat, 'sales' as type
            , case
               when w.week = 1 then t.SalesWeek1
               /* Other weeks */
               when w.week = 11 then t.SalesWeek11
            end as value
        from Sales t
        cross join w
        )
select
      u.Product, u.Plant
    , max(case when type = 'production' then value end) as production
    , max(case when type = 'sales' then value end) as sales
    , week, week_date
from unpiv u
group by
      u.Product, u.Plant
    , week, week_date
order by
      u.Product, u.Plant
    , week, week_date
产品 植物 生产 销售 周_日期
10011 ABC32 6742 425 1 2001-01-01
10011 ABC32 3645 364 11 2001-06-18
10011 DEF10 3579 879 1 2001-01-01
10011 DEF10 8761 501 11 2001-06-18
45891 GHI22 8945 904 1 2001-01-01
45891 GHI22 1556 395 11 2001-06-18

小提琴

这是第二种(仅略有不同)方法:https://dbfiddle.uk/pC0wmedZ

© www.soinside.com 2019 - 2024. All rights reserved.