【问题标题】:Recursive CTE in Amazon RedshiftAmazon Redshift 中的递归 CTE
【发布时间】:2019-01-22 14:42:31
【问题描述】:

我们正在尝试移植代码以在 Amazon Redshift 上运行,但 Refshift 不会运行递归 CTE 函数。有知道如何移植这个的好人吗?

with tt as (
      select t.*, row_number() over (partition by id order by time) as seqnum
      from t
     ),     
     recursive cte as (
      select t.*, time as grp_start
      from tt
      where seqnum = 1
      union all
      select tt.*,
             (case when tt.time < cte.grp_start + interval '3 second'
                   then tt.time
                   else tt.grp_start
               end)
      from cte join
           tt
           on tt.seqnum = cte.seqnum + 1
     )
select cte.*,
       (case when grp_start = lag(grp_start) over (partition by id order by time)
             then 0 else 1
        end) as isValid
from cte;

或者,一个不同的代码来重现下面的逻辑。

  • 这是一个二进制结果:
  • 如果它是 ID 的第一个已知值,则为 1
  • 如果比该 ID 的前一个“1”晚 3 秒或更晚,则为 1
  • 如果比该 ID 的前一个“1”小于 3 秒,则为 0

注意 1:这不是上一条记录的秒数差异
注2:数据集中有很多ID
注3:原始数据集有ID和日期

期望的输出: https://i.stack.imgur.com/k4KUQ.png

数据集 poc: http://www.sqlfiddle.com/#!15/41d4b

【问题讨论】:

  • 我不认为 Redshift 支持递归 CTE,因为它基于 Postgres 的一个非常古老的分支。因此,您应该改为编辑您的问题,并重点解释您的查询背后的逻辑、它的作用,然后可能会提供一些示例数据。
  • 我认为 RedShift 基于 PostgreSQL 8.x。当时不支持 CTE。
  • 是的@The Impaler,这就是我寻求帮助的原因:>
  • 我认为 Redshift 不太适合您的需求(如果您真的需要 CTE)。然而,Amazon Web Services 提供 PostgreSQL 9.x、10.x(甚至 beta 11.x)。也许你应该考虑这些版本之一。
  • 谢谢。有关如何使用 Redshift 处理此问题的任何想法?我不认为此时使用其他平台是可行的

标签: sql date port amazon-redshift calculated-columns


【解决方案1】:

下面的代码可以帮助你。

SELECT id, time, CASE WHEN sec_diff is null or prev_sec_diff - sec_diff > 3
    then 1
    else 0
  end FROM (
    select id, time, sec_diff, lag(sec_diff) over(
      partition by id order by time asc
    )
    as prev_sec_diff
    from (
      select id, time, date_part('s', time - lag(time) over(
        partition by id order by time asc
      )
    )
    as sec_diff from hon
  ) x
) y

【讨论】:

    【解决方案2】:

    在撰写本文时,Redshift 确实支持递归 CTE:see documentation here

    在 Redshift 中创建递归 CTE 时的注意事项:

    • 开始查询:with recursive
    • 列名必须为所有递归 cte 声明

    考虑以下使用递归 CTE 创建日期列表的示例:

    with recursive
          start_dt as (select current_date s_dt)
          , end_dt as (select dateadd(day, 1000, current_date) e_dt)
          -- the recusive cte, note declaration of the column `dt`
          , dates (dt) as (
                -- start at the start date
                select s_dt dt from start_dt
                union all
                -- recursive lines
                select dateadd(day, 1, dt)::date dt  -- converted to date to avoid type mismatch
                from dates
                where dt <= (select e_dt from end_dt)  -- stop at the end date
          )
    select *
    from dates
    

    【讨论】:

      猜你喜欢
      • 2018-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多