【问题标题】:Create a delimitted string from a query in DB2从 DB2 中的查询创建定界字符串
【发布时间】:2014-01-29 21:58:26
【问题描述】:

我正在尝试从 iSeries (AS/400) 上的 DB2 中的查询结果创建一个定界字符串。我已经在 T-SQL 中完成了这项工作,但在这里找不到方法。

这是我在 T-SQL 中的代码。我正在寻找 DB2 中的等价物。

DECLARE @a VARCHAR(1000)
SELECT @a = COALESCE(@a + ', ' + [Description], [Description])
FROM AP.Checkbooks
SELECT @a

如果我的表格中的描述如下所示:

描述 1
描述 2
描述 3

然后它会返回这个:

描述1,描述2,描述3

【问题讨论】:

  • 在 MySQL 中,这将是 'GROUP_CONCAT()'。

标签: sql db2 ibm-midrange


【解决方案1】:

实际上,您正在寻找与 DB2 中 MySQL 的 GROUP_CONCAT 聚合函数等效的功能。根据one thread I found,您可以通过XMLAGG 函数来模仿这种行为:

create table t1 (num int, color varchar(10));

insert into t1 values (1,'red'), (1,'black'), (2,'red'), (2,'yellow'), (2,'green');

select num,
  substr( xmlserialize( xmlagg( xmltext( concat( ', ', color ) ) ) as varchar( 1024 ) ), 3 )
  from t1
  group by num;

这会返回

1 red,black
2 red,yellow,green

(或者应该,如果我没看错的话)

【讨论】:

  • +1,旁注:如果您在 Z/OS v10 上运行,则将 as varchar(1024) 更改为 as clob(1024)
  • 我多年来一直在寻找这个。这正是我需要的。谢谢。
  • 这样的答案应该有一个+10按钮。
【解决方案2】:

您可以使用公用表表达式 (CTE) 和递归来做到这一点。

with                                                                
    cte1 as                                                             
        (select description, row_number() over() as row_nbr from checkbooks),

    cte2 (list, cnt, cnt_max) AS                              
        (SELECT VARCHAR('', 32000), 0, count(description) FROM cte1
         UNION ALL                                                        
         SELECT 
             -- No comma before the first description
             case when cte2.list = '' THEN RTRIM(CHAR(cte1.description)) 
                  else cte2.list || ', ' || RTRIM(CHAR(cte1.description)) end,   
                  cte2.cnt + 1, 
                  cte2.cnt_max                                
         FROM   cte1,cte2                                                 
         WHERE  cte1.row_nbr = cte2.cnt + 1 AND cte2.cnt < cte2.cnt_max ),                             

    cte3 as                                                          
        (select list from cte2 
         where cte2.cnt = cte2.cnt_max fetch first 1 row only)

select list from cte3;

【讨论】:

    【解决方案3】:

    我正在尝试在 OLEDB 中执行此操作,据我了解,您无法执行此操作,因为您无法在 SQL 中为 OLEDB 执行任何花哨的操作,例如声明变量或创建表。所以我想没有办法。

    【讨论】:

    • 我不确定这是否是对我的回答的评论,但我的回答没有声明变量或创建表。不过,您可能无法使用XMLAGG
    • 正确,我想我没有 XMLAGG,因为它无法识别 OLEDB 查询中的任何内容。
    • 他可以使用数据库功能
    【解决方案4】:

    如果您运行的是 DB2 9.7 或更高版本,则可以使用 LISTAGG 函数。看看这里: http://pic.dhe.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=%2Fcom.ibm.db2.luw.sql.ref.doc%2Fdoc%2Fr0058709.html

    【讨论】:

      最近更新 更多