如何在没有子查询的情况下在一列中聚合行?

时间:2017-08-25 09:48:48

标签: sql oracle

我有这样的结构:

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不能“分组”别名(“重要的事情”)。

所以,我需要你的建议。对我来说,使这个查询更快一点并不是那么重要,我想知道如何以另一种方式解决这个问题。

2 个答案:

答案 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;