LISTAGG 相当于 10 克 [重复]

Posted

技术标签:

【中文标题】LISTAGG 相当于 10 克 [重复]【英文标题】:LISTAGG equivalent for 10g [duplicate] 【发布时间】:2018-05-21 09:28:34 【问题描述】:

我使用的是 Oracle 10g,所以很遗憾我不能使用 listagg(因为这需要 11g)。

所以我想将下面的代码移植到 10g 的替代方案:

select count(*) from (
    select listagg(flag) within group (order by dt) as flags
    from   temp_output_ovlp
)
where not regexp_like(flags, 'HH|EE|HS|SE');

这将在运行时在EHEEESHEHH 中搜索匹配的HH|EE|HS|SE 模式:

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
|  10      |  E       |
|  20      |  H       |
|  30      |  E       |
|  40      |  E       |
|  50      |  E       |
|  60      |  S       |
|  70      |  H       |
|  75      |  E       |
|  80      |  H       |
|  100     |  H       |
|----------|----------|

demo

我按照here 的建议尝试了lag,在 10g 上可用,但没有成功:

select (case when count(*) = sum(case when flag2 not in ('HH', 'EE', 'HS', 'SE')
             then 1 else 0
        end) as return_value
from (select t.*,
             (lag(flag) over (order by dt) || flag) as flag2
      from temp
     ) t;

问题

    谁能告诉我如何让它工作? COLLECT(参见here)在性能方面与lag 相比如何?

谢谢

编辑:

预期结果

EHEEESHEHH 必须返回 1,因为至少可以在 EHEEESHEHH 中找到以下两个字母模式 (HH|EE|HS|SE) 之一(此处为 EEHH)。 如果模式是 EHESSSHEHE,则必须返回 0,因为在 EHESSSHEHE 中找不到以下两个字母模式 (HH|EE|HS|SE)。

注意:模式(例如EHEEESHEHH)如果内部查询SELECT listagg(FLAG) WITHIN GROUP (ORDER BY DT) as flags FROM TEMP_OUTPUT_OVLP对数据表的结果。

【问题讨论】:

请通过编辑问题提供预期的输出。 谢谢,添加了预期的结果 asktom.oracle.com/pls/asktom/… @a_horse_with_no_name 该问题与您提供的链接不重复。这个是不用listagg(11g)的,这个链接是为了使用listagg。它使用滞后。谢谢 请参阅已接受答案中的“10g 及以下”​​部分。 【参考方案1】:

如果它对任何人有帮助,得到的工作如下:

    SELECT DECODE(return_value,0,0,1) result 
    FROM (SELECT 
            SUM(CASE WHEN (flag2 in ('HH', 'EE', 'HS', 'SE'))
                THEN 1 ELSE 0 
                END) AS return_value
    FROM (SELECT
            (lag(flag) over (ORDER BY DT) || flag) AS flag2
              FROM TEMP_OUTPUT_OVLP)
    ) t;

它将返回 1 用于:

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
|  10      |  E       |
|  20      |  H       |
|  30      |  E       |
|  40      |  E       |
|  50      |  E       |
|  60      |  S       |
|  70      |  H       |
|  75      |  E       |
|  80      |  H       |
|  100     |  H       |
|----------|----------|

还有0

|----------|----------|
|  DT      |  FLAG    |
|----------|----------|
|  10      |  E       |
|  20      |  H       |
|  30      |  E       |
|  40      |  H       |
|  50      |  E       |
|  60      |  S       |
|  70      |  H       |
|  75      |  E       |
|  80      |  H       |
|  100     |  E       |
|----------|----------|

正如预期的那样。

【讨论】:

【参考方案2】:

这并不重要(因为您已经找到了解决方案),但是 - 也许您会对在 10g 中聚合值的另外两个选项感兴趣。

这个是安全使用:

SQL> select rtrim(xmlagg(xmlelement(e, dname ||',') order by deptno).extract('//text()'), ',') depts
  2  from dept;

DEPTS
--------------------------------------------------------------------------------
ACCOUNTING,RESEARCH,SALES,OPERATIONS

WM_CONCAT 未记录,因此您最好不要使用它,因为 Oracle 可能会决定从未来版本中删除它,所以...再见向后兼容性。

SQL> select wm_concat(dname) depts
  2  from dept;

DEPTS
--------------------------------------------------------------------------------
ACCOUNTING,RESEARCH,SALES,OPERATIONS

SQL>

【讨论】:

感谢您提供这些替代方案。必须检查一个是否比其他更快。 不客气!

以上是关于LISTAGG 相当于 10 克 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL:如何删除 listagg 中的重复项

oracle sql listagg [重复]

几寸蛋糕多少磅

横向压平两列,雪花中不重复

oracle 10g怎么实现 listagg功能

oracle 10g中listagg的替代品