【问题标题】:Recursive CTE Alternative for Concatenating Strings in Redshift在 Redshift 中连接字符串的递归 CTE 替代方案
【发布时间】:2020-05-18 11:21:11
【问题描述】:

我有一个表,其中有 4 列,即:Book_no,Prev_Book_no(上一版 book_no),Edition_no(从 0 开始到最新版 no(以 1 递增)),Tree(最初为 null)。

我打算做的是从最高版本到第0版创建一棵Book_no树。

例如: (Book_no,Prev_Book_no,Edition_no) 值: (bbb,null,0), (ccc,bbb,1), (ddd,ccc,2), (eee,ddd,3), (fff,eee,4)

那么每一行的树应该是:(bbb),(ccc,bbb),(ddd,ccc,bbb),(eee,ddd,ccc,bbb) 和 (fff,eee,ddd,ccc,bbb) .

为此,我尝试使用递归 CTE,代码如下:

with cte(book_no,prev_book_no,tree,edition_no) as

(select

book_no,prev_book_no,tree,edition_no

from books

where edition_no>=0

union all

select e.book_no,e.prev_book_no,concat(nvl(e.tree,''),','+e.prev_book_no),e.edition_no

from

cte e inner join books f

on e.prev_book_no=f.book_no

)

select distinct * from cte

order by edition_no;

但是 Redshift 不允许在 from 子句中使用 cte table 并给出错误。 '表 cte 不存在'。

P.S 表中有多种不同的书。例如我只提到了一本。

在 Redshift 中是否有任何替代方案?

编辑:

样本数据:

预期输出:

逻辑:我想获得书号的层次结构,并且正在使用 concat 操作。(当前代码可能是错误的) 谢谢!

【问题讨论】:

  • 请提供示例数据、期望的结果以及您要实现的逻辑的清晰说明。
  • @GordonLinoff 我已经添加了相关图片,并试图解释我打算做什么。

标签: sql amazon-redshift string-concatenation recursive-cte


【解决方案1】:

从 2021 年 4 月 29 日开始,Redshift 现在使用 WITH RECURSIVE 语法支持递归 CTE:

WITH RECURSIVE cte(book_no, prev_book_no, tree, edition_no) AS (
    SELECT book_no, prev_book_no, tree, edition_no
    FROM books
    WHERE edition_no >= 0
    UNION ALL
    SELECT e.book_no, e.prev_book_no, NVL(e.tree,'')||','||e.prev_book_no), e.edition_no
    FROM cte         e
    INNER JOIN books f ON e.prev_book_no = f.book_no)
SELECT DISTINCT *
FROM cte
ORDER BY
    edition_no;

https://aws.amazon.com/about-aws/whats-new/2021/04/amazon-redshift-announces-support-for-heirarchical-data-queries-with-recursive-cte/ https://docs.aws.amazon.com/redshift/latest/dg/r_WITH_clause.html#r_WITH_clause-recursive-cte

【讨论】:

    【解决方案2】:

    您正确选择了递归 CTE。不幸的是,Redshift does not support them。另见this similar question。我不知道任何可以被视为全值解决方法的 SQL 功能。也许如果级别的数量实际上是有限的,您可以使用有限数量的左自连接(丑陋,我知道)。

    (对于您的 CTE - 虽然有点偏离主题 - 似乎条件 where edition_no=0 足以作为联合第一部分的种子,第二个查询中的连接条件也应转换为 on f.prev_book_no=e.book_no。)

    【讨论】:

    • 谢谢!但关卡数量不限,因书而异。
    【解决方案3】:

    Amazon Redshift 数据库不支持递归查询。 https://docs.aws.amazon.com/redshift/latest/dg/c_unsupported-postgresql-features.html

    我不擅长这个方言。试试这个代码,可能它可以工作并解决你的问题:

    select book_no,prev_book_no,edition_no,
    (
    select listagg(innr.book_no,',') within group (order by innr.edition_no asc) over() 
    from books innr 
    where innr.book_no=outr.book_no and innr.edition_no<=outr.edition_no
    ) tree
    from books outr
    order by book_no
    

    带有循环的变体。尝试执行它:

    create local temporary table IF NOT EXISTS 
    table1 (book_id bigint, book_no varchar(10), edition_no varchar(10));
    
    insert into table1 (book_id, book_no, edition_no) 
    select row_number () over (order by book_no) as book_id, book_no, edition_no 
    from books where edition_no=0;
    
    FOR iter IN SELECT distinct edition_no 
    FROM books where edition_no!=0 ORDER BY edition_no LOOP
      insert into table1 (book_id, book_no, edition_no) 
      select t.book_id, b.book_no, b.edition_no 
      from table1 t join books b on t.book_id=b.prev_book_no
      where b.edition_no = iter
      ;
      commit;
      END LOOP;
    
    select book_no,prev_book_no,edition_no,
    (
    select listagg(innr.book_no,',') within group (order by innr.edition_no asc) over() 
    from books innr inner join table1 tbl_innr on innr.book_no=tbl_innr.book_no
    where tbl_innr.book_id=tbl_outr.book_id and innr.edition_no<=outr.edition_no
    ) tree
    from books outr join table1 tbl_outr on outr.book_no=tbl_outr.book_no
    order by book_no
    ;
    drop table table1;
    

    【讨论】:

    • 感谢您的解决方案。但它似乎只适用于一棵这样的树,当我在整个数据集上尝试它时,它会给出错误:结果大小超过 LISTAGG 限制。 (可能它将所有书籍分组为特定版本号)。你能把它也包含在你的代码中吗?
    • @NewCoder 你有整本书的ID吗(所有版本都一样)?
    • 不,没有这个ID栏
    • @NewCoder 我刚刚添加了新版本。试试看
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    • 2018-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多