SQL联接子查询问题/性能

时间:2019-09-15 02:46:08

标签: sql postgresql

是否可以编写查询来获得与以下“虚构”查询相同的结果集?

CREATE OR REPLACE VIEW v_report AS
    SELECT
        meta.refnum         AS  refnum,
        codes.svc_codes     AS  svc_codes
    FROM
        t_bill AS meta

    JOIN (SELECT
        string_agg(p.service_code, ':') AS svc_codes
      FROM
        t_bill_service_services AS p
      WHERE
        p.refnum = meta.refnum
    ) AS codes
    ON meta.refnum = codes.refnum

该查询是虚构的,因为它不会运行有关meta.refnum子句中的WHERE的错误消息,而该错误消息无法从查询的这一部分中引用。

注1:为简洁起见,省略了许多其他表中的许多列,这些列也已加入。这可能会排除一些更简单的解决方案,从而消除了子查询。

注2:可以通过将p.refnum列添加到子查询并执行GROUP BY p.refnum并删除WHERE来使这项工作(对于“工作”的某些定义)有效总共,但这当然意味着整个t_bill_service_services表都将被扫描和排序-对于我的情况,非常非常慢,因为该表相当大。

(SQL风格是Postgres,但应该无关紧要,因为只有string_agg()调用应该是非标准SQL。)

2 个答案:

答案 0 :(得分:1)

您可以将子查询放在查询的JOIN部分中,而不是SELECT到派生表中。在本节中,您可以在子查询中访问父表中的值,因此只能汇总其他表中的相关条目。例如:

select meta.refnum,
       (SELECT string_agg(p.service_code, ':')
        FROM t_bill_service_services AS p
        WHERE p.refnum = meta.refnum
       ) AS svc_codes
from t_bill meta

Demo on dbfiddle

答案 1 :(得分:1)

您所描述的是横向联接-Postgres支持这些联接。您可以将查询编写为:

SELECT meta.refnum         AS  refnum,
       codes.svc_codes     AS  svc_codes
FROM t_bill meta CROSS JOIN LATERAL
     (SELECT string_agg(p.service_code, ':') AS svc_codes
      FROM t_bill_service_services p
      WHERE p.refnum = meta.refnum
     ) codes;

在这种情况下,横向联接非常类似于相关子查询(Nick的答案)。但是,横向联接的功能要强大得多,因为它允许子查询返回多列和多行。

相关问题