涉及 LISTAGG 的 DB2 SQL

Posted

技术标签:

【中文标题】涉及 LISTAGG 的 DB2 SQL【英文标题】:DB2 SQL involving LISTAGG 【发布时间】:2021-05-17 20:13:39 【问题描述】:

我有一个如下所示的数据集

  DEPT_ID  EMP_NM   STATUS_DATE    LEFT_FLAG      STATUS_CHANGE
    1       ABC      20200131        0            N
    1       DEF      20200204        0            N
    1       DEF      20200504        0            Y
    1       XYZ      20201210        0            N
    1       MNO      20201210        0            N
    1       DEF      20201230        1            N
    1       XYZ      20201230        0            Y
    1       PQR      20210123        0            N
    1       ABC      20210228        1            N
    1       XYZ      20210228        1            N

现在我想生成如下输出

  DEPT_ID  EMP_NM               STATUS_DATE    
    1       ABC                  20200131        
    1       ABC,DEF              20200204  
    1       ABC,DEF              20200504      
    1       ABC,DEF,XYZ,MNO      20201210        
    1       ABC,XYZ,MNO          20201230        
    1       ABC,XYZ,MNO,PQR      20210123        
    1       MNO,PQR              20210228   

我尝试使用 LISTAGG,但无法消除重复项,也无法在 LEFT_FLAG=1 时删除

【问题讨论】:

你的逻辑不是 100% 清楚的。这些行不是累积的。 【参考方案1】:

如果我理解正确,您每次都需要一份员工名单。状态标志似乎必须相关。

这个版本应该可以在 DB2 中工作:

select dept_id, status_date, listagg(emp_nm, ',') within group (order by emp_nm)
from (select t.dept_id, t.status_date, t2.status_date as status_date_2, t2.left_flag, t2.emp_nm,
              row_number() over (partition by t.status_date, t2.dept_id, t2.emp_nm order by t2.status_date desc) as seqnum
      from (select dept_id, status_date
            from t 
            group by dept_id, status_date
           ) t left join
           t t2
           on t2.dept_id = t.dept_id and t2.status_date <= t.status_date
     ) tt2
where seqnum = 1 and left_flag = 0
group by dept_id, status_date;

Here 是一个 dbfiddle。

这个版本不是因为关联子句嵌套得太深,唉,对于 DB2:

select t.dept_id, t.status_date,
       (select listagg(t2.emp_nm, ',') within group (order by t2.emp_nm)
        from (select t2.emp_nm,
                     row_number() over (partition by t2.dept_id, t2.emp_nm order by t2.status_date desc) as seqnum
              from t t2
              where t2.status_date <= t.status_date and
                    t2.dept_id = t.dept_id
             ) t2
        where t2.seqnum = 1 and t2.left_flag = 0
       ) as emps
from t
group by dept_id, status_date;

【讨论】:

在 db2 v11.x 中是否支持? 应该在 DB2 LUW 10.5+ 中工作。 LISTAGG() 在 DB2 中没有下划线。 没有找到 t2.left_flag。因为它不在 t2 内 它在所有行的 emps 中给了我相同的值 它仍然没有处理left_flag。表示 left_flag 我想删除那些 emps

以上是关于涉及 LISTAGG 的 DB2 SQL的主要内容,如果未能解决你的问题,请参考以下文章

DB2-具有DISTINCT子句的LISTAGG()-不起作用?

H2 用户定义的聚合函数 ListAgg 不能在第一个参数上使用 DISTINCT 或 TRIM()

按组的 DB2 逗号分隔输出

DB2 中涉及会话表的选择查询执行缓慢

关于ORACLE列转行的问题

需要帮助优化涉及数百万条记录的非常慢的 DB2 SQL 查询