是否可以编写查询来获得与以下“虚构”查询相同的结果集?
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。)
答案 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
答案 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的答案)。但是,横向联接的功能要强大得多,因为它允许子查询返回多列和多行。