我有这样的结构:
with
pages ( id, sid, text ) as (
select 1, 1, 'lorem ipsum' from dual union all
select 2, 1, 'lorem ipsum2' from dual union all
select 3, 1, 'lorem ipsum3' from dual union all
select 4, 1, 'lorem ipsum4' from dual ),
responsible ( id, pid, name, sirname ) as (
select 1, 1, 'Alexey', 'Ivanov' from dual union all
select 2, 1, 'Igor', 'Petrov' from dual union all
select 3, 1, 'Dmitriy', 'Shestakov' from dual)
等选择:
select
p.id, p.sid,
CASE
WHEN 1=1 THEN p.text
ELSE p.text
END AS "Important thing",
(select listagg (name || '-' || sirname, '; ') within group (order by id) from responsible where pid = p.sid) as "SA"
from
pages p
order by
p.id;
输出:
--------------------------
ID SID Important thing SA
1 1 lorem ipsum Alexey-Ivanov; Igor-Petrov; Dmitriy-Shestakov
2 1 lorem ipsum2 Alexey-Ivanov; Igor-Petrov; Dmitriy-Shestakov
3 1 lorem ipsum3 Alexey-Ivanov; Igor-Petrov; Dmitriy-Shestakov
4 1 lorem ipsum4 Alexey-Ivanov; Igor-Petrov; Dmitriy-Shestakov
这是我想要的工作。它添加到每个pages.id所有负责.name + sirname的。 但我不喜欢我使用嵌套查询,因为在真实数据库中有超过9000个pages.sid。所以我担心这个SQL查询不会那么快,数据库管理员会惩罚我:)。
我知道,我可以使用JOIN,但我不知道如何为每个pages.sid聚集所有名称+ sirname。我想,我可以使用listagg,但我知道Oracle不能“分组”别名(“重要的事情”)。
所以,我需要你的建议。对我来说,使这个查询更快一点并不是那么重要,我想知道如何以另一种方式解决这个问题。
答案 0 :(得分:0)
您可以改为加入一个执行文本聚合的子查询,而不是在SELECT
子句中使用子查询:
SELECT
p.id,
p.sid,
p.text AS "Important thing",
r.sa
FROM pages p
LEFT JOIN
(
SELECT
pid,
LISTAGG (name || '-' || sirname, '; ') WITHIN GROUP (ORDER BY id) AS sa
FROM responsible
) r
ON r.pid = p.sid
ORDER BY p.id;
您当前的方法使用相关子查询,Oracle可能无法进行太多优化。这种连接方法使用了一个非相关的子查询,而Oracle已经试图让它运行得更快。
答案 1 :(得分:0)
在这种情况下,您可以简化查询:
select p.id, p.sid, p.text,
listagg (name || '-' || sirname, '; ') within group (order by r.id) SA
from pages p
left join responsible r on r.pid = p.sid
group by p.id, p.sid, p.text
order by p.id;