我可以在 Redshift 上的存储过程中将两个查询连接在一起吗?

Posted

技术标签:

【中文标题】我可以在 Redshift 上的存储过程中将两个查询连接在一起吗?【英文标题】:Can I join two queries together in a Stored procedure on Redshift? 【发布时间】:2019-07-12 04:45:31 【问题描述】:

最初我正在尝试使用函数但无济于事。 Redshift 不允许表返回类型或从表中选择数据。我希望也许有一种方法可以使用存储过程来做到这一点,但我不再有信心了。我为下面列出的代码创建了一个 SP,是否可以为 SP 将两个查询连接到自身?

尝试做一个功能,但不可能发生

YTD current year
select 
   year
  , month
  , revenue
  ,transactiondate
  , Flag
from (
select
  extract(year from transactiondate) as year
  , to_char(transactiondate, 'Mon') as month
  , extract(month from transactiondate) as month_number
  , sum(netamount) as revenue
  ,transactiondate
  ,Flag
from
  vw_costs_of_businesss_copy

--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(transactiondate, 'YYYY-MM-DD') ->=  concat(to_char(extract(year from '2019-01-01'), 'YYYY'),'01-01') --Convert the date param to year and concatenate with '01/01'
--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(concat(to_char(extract(year from to_date('2019-01-01', 'YYYY-MM-DD'))),'01-01') , 'YYYY-MM-DD') >= '2019-01-01' --Convert the date param to year and concatenate with '01/01'
--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(concat(to_char(Cas(extract(year from to_date('2019-01-01', 'YYYY-MM-DD')) as text ),'-01-01') , 'YYYY-MM-DD') >= '2019-01-01' --Convert the date param to year and concatenate with '01/01'
--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(concat(to_char(Cast(extract(year from to_date('2019-01-01', 'YYYY-MM-DD')) as Text),'0000'),'-01') , 'YYYY-MM-DD') >= '2019-01-01' --Convert the date param to year and concatenate with '01/01'
where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(transactiondate, 'YYYY-MM-DD')>= to_date(concat(to_char(Cast(extract(year from to_date('2019-01-01', 'YYYY-MM-DD')) as Text),'0000'),'-01') , 'YYYY-MM-DD')

group by
  year
  , month
  , month_number
  ,transactiondate
 , Flag
)
order by month_number, year

--YTD PREV YEAR
select 
   year
  , month
  , revenue
  ,transactiondate
  , Flag
from (
select
  extract(year from transactiondate) as year
  , to_char(transactiondate, 'Mon') as month
  , extract(month from transactiondate) as month_number
  , sum(netamount) as revenue
  ,transactiondate
  ,Flag
from
  vw_costs_of_businesss_copy

--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(transactiondate, 'YYYY-MM-DD') ->=  concat(to_char(extract(year from '2019-01-01'), 'YYYY'),'01-01') --Convert the date param to year and concatenate with '01/01'
--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(concat(to_char(extract(year from to_date('2019-01-01', 'YYYY-MM-DD'))),'01-01') , 'YYYY-MM-DD') >= '2019-01-01' --Convert the date param to year and concatenate with '01/01'
--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(concat(to_char(Cas(extract(year from to_date('2019-01-01', 'YYYY-MM-DD')) as text ),'-01-01') , 'YYYY-MM-DD') >= '2019-01-01' --Convert the date param to year and concatenate with '01/01'
--where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(concat(to_char(Cast(extract(year from to_date('2019-01-01', 'YYYY-MM-DD')) as Text),'0000'),'-01') , 'YYYY-MM-DD') >= '2019-01-01' --Convert the date param to year and concatenate with '01/01'
where to_date(transactiondate, 'YYYY-MM-DD') <= '2019-06-07' and to_date(transactiondate, 'YYYY-MM-DD')>= to_date(concat(to_char(Cast(extract(year from to_date('2019-01-01', 'YYYY-MM-DD')-1) as Text),'0000'),'-01') , 'YYYY-MM-DD')

group by
  year
  , month
  , month_number
  ,transactiondate
 , Flag
)

order by month_number, year

它需要列出 YTD 和 prev_YTD 以便我可以将其作为参数传递,这可能吗?我意识到我必须为此制作一张桌子。 我在哪里放置 Prev_year、Prev-month 列

【问题讨论】:

【参考方案1】:

我认为您正在寻找UNION ALL 的概念来“加入两个查询”。

这是一个使用存储过程的示例。请参阅"Overview of Stored Procedures in Amazon Redshift" 了解更多信息。

CREATE PROCEDURE ytd_comparison(
      date_param IN    DATE
    , result_set INOUT REFCURSOR) 
AS $$
BEGIN
    OPEN result_set FOR --YTD
    SELECT year , month , revenue , transactiondate , Flag
    FROM (SELECT EXTRACT(year FROM transactiondate) AS year
               , TO_CHAR(transactiondate, 'Mon') AS month
               , EXTRACT(month FROM transactiondate) AS month_number
               , SUM(netamount) AS revenue
               , transactiondate
               , Flag
          FROM vw_costs_of_businesss_copy
          WHERE TO_DATE(transactiondate, 'YYYY-MM-DD') <= date_param
            AND TO_DATE(transactiondate, 'YYYY-MM-DD') >= DATE_TRUNC('year',date_param)
          GROUP BY year , month , month_number , transactiondate , Flag
          )
    UNION ALL --YTD PREV YEAR
    SELECT year ,month ,revenue ,transactiondate ,Flag
    FROM (SELECT EXTRACT(year FROM transactiondate) AS year
               , TO_CHAR(transactiondate, 'Mon') AS month
               , EXTRACT(month FROM transactiondate) AS month_number
               , SUM(netamount) AS revenue
               , transactiondate
               , Flag
          FROM vw_costs_of_businesss_copy
          WHERE TO_DATE(transactiondate, 'YYYY-MM-DD') <= DATEADD(year, -1, date_param)
            AND TO_DATE(transactiondate, 'YYYY-MM-DD') >= DATE_TRUNC('year', DATEADD(year, -1, date_param))
          GROUP BY year , month , month_number , transactiondate , Flag
          )
    ORDER BY month_number , year
    ;
    RETURN;
END;
$$ LANGUAGE plpgsql;

您需要在调用过程时为输出REFCURSOR 提供名称。您必须使用BEGIN 打开一个事务来维护游标,然后从REFCURSOR 获取输出,然后使用END 事务丢弃结果游标。

BEGIN;
CALL ytd_comparison ('2016-07-01'::DATE, 'ytd_results'); 
FETCH ALL FROM ytd_results; 
END;

更新: 或者,您可以仅创建前一天的视图。

CREATE OR REPLACE VIEW ytd_comparison AS
SELECT year , month , revenue , transactiondate , Flag
FROM (SELECT EXTRACT(year FROM transactiondate) AS year
           , TO_CHAR(transactiondate, 'Mon') AS month
           , EXTRACT(month FROM transactiondate) AS month_number
           , SUM(netamount) AS revenue
           , transactiondate
           , Flag
      FROM vw_costs_of_businesss_copy
      WHERE TO_DATE(transactiondate, 'YYYY-MM-DD') <= GETDATE() - 1
        AND TO_DATE(transactiondate, 'YYYY-MM-DD') >= DATE_TRUNC('year',GETDATE() - 1)
      GROUP BY year , month , month_number , transactiondate , Flag
      )
UNION ALL --YTD PREV YEAR
SELECT year ,month ,revenue ,transactiondate ,Flag
FROM (SELECT EXTRACT(year FROM transactiondate) AS year
           , TO_CHAR(transactiondate, 'Mon') AS month
           , EXTRACT(month FROM transactiondate) AS month_number
           , SUM(netamount) AS revenue
           , transactiondate
           , Flag
      FROM vw_costs_of_businesss_copy
      WHERE TO_DATE(transactiondate, 'YYYY-MM-DD') <= DATEADD(year, -1, GETDATE() - 1)
        AND TO_DATE(transactiondate, 'YYYY-MM-DD') >= DATE_TRUNC('year', DATEADD(year, -1, GETDATE() - 1))
      GROUP BY year , month , month_number , transactiondate , Flag
      )
ORDER BY month_number , year
;

【讨论】:

从这一点开始的问题是可以把它做成一个视图或表格吗? 要使其成为视图或表格,您必须计算每一天的值,然后在查询时仅过滤您想要的那一天。如果存储过程不合适,使用准备好的语句可能会更好。 docs.aws.amazon.com/redshift/latest/dg/r_PREPARE.html 我只需要它直到今天以及过去两年的年初至今和当月。但是,查看准备语句,我需要传递您重新处理的 SP 给我的结果集中的值。 在这种情况下,是的,你可以很容易地做到这一点。在答案中添加了示例。 老兄你最好的。有时它的蚂蚁小山我们制造了山,但对于我的生活,我可以弄清楚如何做到这一点。真的非常感谢您的帮助!

以上是关于我可以在 Redshift 上的存储过程中将两个查询连接在一起吗?的主要内容,如果未能解决你的问题,请参考以下文章

Redshift 存储过程被中止

AWS Redshift:从 S3 上的许多存储桶加载数据

如何在 Redshift 中将十六进制数转换为二进制数?

如何使用自动化或命令行工具管理 AWS Redshift 中的存储过程?

在Redshift返回错误的存储过程中传递变量

是否可以将可变数量的参数传递给redshift中的存储过程?