Reputation: 4449
Is there a way to write a query to obtain the same result set as the following "imaginary" query?
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
This query is imaginary because it won't run with an error message about the meta.refnum
in the WHERE
clause not being able to be referenced from this part of the query.
Note 1: many columns from a variety of other tables which are also JOINed are omitted in the interest of brevity. This may preclude some simpler solutions which eliminate the subquery.
Note 2: it is possible to make this work (for some definitions of "work") by adding the p.refnum
column to the subquery and doing a GROUP BY p.refnum
and removing the WHERE
altogether, but this of course means the entire t_bill_service_services table gets scanned and sorted -- very very slow for my situation, as the table is reasonably large.
(The SQL flavor is Postgres, but should be irrelevant, as only the string_agg()
call should be non-std SQL.)
Upvotes: 0
Views: 42
Reputation: 1269443
What you are describing is a lateral join -- and Postgres supports these. You can write the query as:
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;
In this case, a lateral join is a lot like a correlated subquery (Nick's answer). However, a lateral join is much more powerful, because it allows the subquery to return multiple columns and multiple rows.
Upvotes: 1
Reputation: 147146
Rather than JOIN
ing to a derived table, you can place the subquery in the SELECT
part of the query. In this section, you can access the values from the parent table in subqueries and so only aggregate the relevant entries in the other table. For example:
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
Upvotes: 1