【发布时间】:2022-11-30 17:39:10
【问题描述】:
我想咨询聚合函数 LISTAGG 的这个问题:
select
r.id,
(
select
LISTAGG(
r.id || '##' || cco.id
,
' '
)
from
(
SELECT
co.id
FROM conditions co
START WITH ID = (select cons.id from conditions cons where cons.role_id = r.id)
CONNECT BY PRIOR co.id = co.parent_condition_id
) cco
) conditions_export
from roles r
where r.id in (570, 571, 569)
--r.id between 569 and 571
-- table roles has 2 fields: id (number), name (varchar2)
-- table conditions has 4 fields: id, parent_condition_id, role_id (number), rule (varchar2)
当我在条件 r.id in (570, 571, 569) 中使用单个 ID(或显式 ID 列表)时,结果符合预期。
当我不使用 where 子句或使用某些动态范围(r.id between 569 and 571、r.id > 500、r.id in (select rr.id from roles rr))时,结果包含每行相同的聚合值 - 结果是错误的(与预期不同)。
我的数据库中的示例:
表角色中的值:
id name
--- -----
569 ROLE1
570 ROLE2
571 ROLE3
表条件中的值:
id parent_condition_id role_id rule
------------------------------------------
1657 NULL 569 deny
1659 NULL 570 allow
1667 NULL 571 and
1674 1668 NULL match
1673 1670 NULL allow
1672 1671 NULL allow
1671 1670 NULL and
1670 1669 NULL and
1669 1668 NULL and
1668 1667 NULL and
查询:... r.id in (570, 571, 569)
结果:
569 569##1657
570 570##1659
571 571##1667 571##1668 571##1669 571##1670 571##1671 571##1672 571##1673 571##1674
查询:... r.id between 569 and 571
结果:
569 569##1657
570 570##1657
571 571##1657
使用此聚合的原因是将当前配置从数据库导出到文本文件。
问题:你有什么想法,如何解决这个问题?
数据库版本为Oracle 19c
【问题讨论】:
-
我没有在 18c、19c (19.16) 或 21c 中看到
... r.id in (570, 571, 569)的结果;与... r.id between 569 and 571相同。但是单独运行它们我可以看到这应该是你从所有这些中得到的结果 - 所以我猜你遇到了一个错误。