填补 redshift 中外连接的空白

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

我有一个包含产品和销售数据的表。不幸的是,并不是每个月都有特定的产品被售出,我希望也能显示特定月份内未售出的产品。在 Oracle 中,查询是这样构建的:https://www.oracle.com/ocom/groups/public/@otn/documents/webcontent/270646.htm.

我想在 Redshift 中执行类似的操作,但我无法使用此处描述的分区。我可以轻松地更换它吗?

数据样本:

WITH dates AS (
    SELECT to_date('2023-01-01', 'YYYY-MM-DD') AS d FROM dual
    UNION ALL
    SELECT to_date('2023-02-01', 'YYYY-MM-DD') AS d FROM dual
    UNION ALL
    SELECT to_date('2023-03-01', 'YYYY-MM-DD') AS d FROM dual
    UNION ALL
    SELECT to_date('2023-04-01', 'YYYY-MM-DD') AS d FROM dual
    UNION ALL
    SELECT to_date('2023-05-01', 'YYYY-MM-DD') AS d FROM dual
)
, product_sales as(
    --Yanuary
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-01-01', 'YYYY-MM-DD') AS sale_date, 3 AS sale_amount FROM dual
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-01-01', 'YYYY-MM-DD') AS sale_date, 8 AS sale_amount FROM dual
    UNION ALL
    SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-01-01', 'YYYY-MM-DD') AS sale_date, 9 AS sale_amount FROM dual
    
    UNION ALL
    
    --February
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 5 AS sale_amount FROM dual
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 2 AS sale_amount FROM dual
    UNION ALL
    SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount FROM dual
    
    UNION ALL
    
    --March
--  SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 5 AS sale_amount FROM dual
--  UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-03-01', 'YYYY-MM-DD') AS sale_date, 7 AS sale_amount FROM dual
--  UNION ALL
--  SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount FROM dual
    
    UNION ALL
    
    --April
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-04-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount FROM dual
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-04-01', 'YYYY-MM-DD') AS sale_date, 2 AS sale_amount FROM dual
--  UNION ALL
--  SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-04-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount FROM dual
    
    UNION ALL
    
    --May
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-05-01', 'YYYY-MM-DD') AS sale_date, 6 AS sale_amount FROM dual
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-05-01', 'YYYY-MM-DD') AS sale_date, 4 AS sale_amount FROM dual
    UNION ALL
    SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-05-01', 'YYYY-MM-DD') AS sale_date, 2 AS sale_amount FROM dual
)


SELECT ps.prod_id, ps.prod_name, nvl(ps.sale_amount, 0) AS sale_amount, da.d AS sale_date
FROM product_sales ps
PARTITION BY(ps.prod_id, ps.prod_name)
RIGHT OUTER JOIN dates da ON ps.sale_date = da.d
ORDER BY da.d, ps.prod_id
sql oracle-database join amazon-redshift
1个回答
0
投票

你就快到了:

WITH dates AS (
    SELECT to_date('2023-01-01', 'YYYY-MM-DD') AS d 
    UNION ALL
    SELECT to_date('2023-02-01', 'YYYY-MM-DD') AS d 
    UNION ALL
    SELECT to_date('2023-03-01', 'YYYY-MM-DD') AS d 
    UNION ALL
    SELECT to_date('2023-04-01', 'YYYY-MM-DD') AS d 
    UNION ALL
    SELECT to_date('2023-05-01', 'YYYY-MM-DD') AS d 
)
, product_sales as(
    --Yanuary
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-01-01', 'YYYY-MM-DD') AS sale_date, 3 AS sale_amount 
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-01-01', 'YYYY-MM-DD') AS sale_date, 8 AS sale_amount 
    UNION ALL
    SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-01-01', 'YYYY-MM-DD') AS sale_date, 9 AS sale_amount 
    
    UNION ALL
    
    --February
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 5 AS sale_amount
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 2 AS sale_amount
    UNION ALL
    SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount
    
    UNION ALL
    
    --March
--  SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 5 AS sale_amount FROM dual
--  UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-03-01', 'YYYY-MM-DD') AS sale_date, 7 AS sale_amount 
--  UNION ALL
--  SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-02-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount FROM dual
    
    UNION ALL
    
    --April
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-04-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount 
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-04-01', 'YYYY-MM-DD') AS sale_date, 2 AS sale_amount 
--  UNION ALL
--  SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-04-01', 'YYYY-MM-DD') AS sale_date, 1 AS sale_amount FROM dual
    
    UNION ALL
    
    --May
    SELECT 1 AS prod_id, 'test1' AS prod_name, to_date('2023-05-01', 'YYYY-MM-DD') AS sale_date, 6 AS sale_amount 
    UNION ALL
    SELECT 2 AS prod_id, 'test2' AS prod_name, to_date('2023-05-01', 'YYYY-MM-DD') AS sale_date, 4 AS sale_amount 
    UNION ALL
    SELECT 3 AS prod_id, 'test3' AS prod_name, to_date('2023-05-01', 'YYYY-MM-DD') AS sale_date, 2 AS sale_amount 
)
, spooge as (
SELECT prod_id, prod_name, coalesce(ps.sale_amount, 0) AS sale_amount, sale_date
FROM product_sales ps
UNION ALL
  select prod_id, prod_name, sale_amount, sale_date 
  from (select prod_id, prod_name, 0 as sale_amount, da.d as sale_date
        from product_sales          
        cross JOIN dates da 
        group by 1, 2, 3, 4
       ) xd    
)
select prod_id, prod_name, sum(sale_amount) as sale_amount, sale_date
from spooge
group by 1, 2, 4
ORDER BY  prod_id, sale_date
© www.soinside.com 2019 - 2024. All rights reserved.