我有接下来的两张桌子:
表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 |
上周的值在其他行中(不需要在第一行中)。有什么帮助吗?
当前的表格可以被描述为“透视”,因为每列都有代表一周的数据。为了理解这一点,您首先需要“逆透视”该数据,虽然您可以使用联合来执行此操作,但简单地将源表交叉连接到代表每周的一组行(即 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