POSTGRES将周列转换成行?

时间:2017-10-04 22:21:57

标签: sql postgresql unpivot generate-series

我的预测表存储当前周,然后预测26周的数量:

CREATE TABLE forecast_listings (
   product    integer NOT NULL
 , current_week_date date 
 , weekplus0  integer NOT NULL DEFAULT 0
 , weekplus1  integer NOT NULL DEFAULT 0
 , weekplus2  integer NOT NULL DEFAULT 0
 , weekplus3  integer NOT NULL DEFAULT 0
 , weekplus4  integer NOT NULL DEFAULT 0
 -- etc
 , weekplus24 integer NOT NULL DEFAULT 0
 , weekplus25 integer NOT NULL DEFAULT 0
);

例如,预测单个项目时,我选择一行最近的current_week_date,然后查看相对周数。

SELECT
unnest(
    array[
    to_char(week_current_date, 'YYYY-MM-DD'),
    to_char(week_current_date + interval '1 weeks', 'YYYY-MM-DD'),
    to_char(week_current_date + interval '2 weeks', 'YYYY-MM-DD'),
    to_char(week_current_date + interval '3 weeks', 'YYYY-MM-DD'),
    to_char(week_current_date + interval '4 weeks', 'YYYY-MM-DD')
    -- ...all the way to 25
    ]
) AS "Week",
unnest(
    array[
    weekplus0,
    weekplus1, 
    weekplus2, 
    weekplus3,
    weekplus4
    -- ...all the way to 25
    ]
) AS "Count"
FROM (
    SELECT * FROM forecast_listings 
    WHERE product_id = 1
    ORDER BY week_current_date DESC
    LIMIT 1
) as row

我想用Postgres做这件事,基本上是取一行并将每周的数字转换成一个带有日期列和计数列的行:

week, count
2017-10-01,100
2017-10-08,200
2017-10-15,150
etc.

1 个答案:

答案 0 :(得分:0)

SELECT to_char(f.week_current_date + interval '1 week' * w, 'YYYY-MM-DD')
     , arr[w+1]
FROM  (
   SELECT week_current_date
        , ARRAY[weekplus0, weekplus1, weekplus2, weekplus3] AS arr  -- add all 26
   FROM   forecast_listings
   WHERE  product_id = 1
   ORDER  BY week_current_date DESC NULLS LAST  -- ?
   LIMIT  1
   ) f
CROSS  JOIN LATERAL generate_series(0, 25) w;

关键功能是CROSS JOIN LATERALgenerate_series()来生成所需的行。使用您在子查询中已有的ARRAY constructor。生成的索引w用于向基准日期添加周数以及访问相应的数组项。记下一个潜伏的1分之一错误,因为默认情况下Postgres数组索引是从1开始的。相关:

由于week_current_date似乎确实允许使用NULL值,因此您可能希望使用ORDER BY week_current_date DESC NULLS LAST 对最后为NULL的行进行排序,否则这些行将位于顶部。参见: