You can much simplify this query by aggregating values in request_reserve
and act_code
before you JOIN
to the big join. This avoids the need for aggregate functions on all the other columns and should generally be much faster for a larger number of rows.
SELECT r.id
,rt.name AS request_type
,to_char(r.timestamp, 'DD/mm/YYYY HH24:mi') AS timestamp
,to_char(r.timestamp, 'YYYY-mm-DD') AS timestamp_filtering
,s.name AS request_state
,u.name || COALESCE(' ' || u.surname, '') AS create_user
,r.id_create_user
,e.name AS enterprise
,c.name AS cause
,rm.id_request_state AS id_state
,rr.act_code
,rd.code AS state_revised
,rs.warehouse
,rr.id_warehouse
FROM request r
LEFT JOIN users u ON u.id = r.id_create_user
LEFT JOIN enterprise e ON e.id = u.id_enterprise
LEFT JOIN request_movements rm ON rm.id = r.id_request_movement
LEFT JOIN request_versions rv ON rv.id = rm.id_version
LEFT JOIN state s ON s.id = rm.id_request_state
JOIN request_type rt ON rt.id = r.id_request_type
LEFT JOIN cause_issue c ON c.id = r.id_cause_issue
LEFT JOIN request_shipment rs ON rs.id_request = r.id
LEFT JOIN warehouse_enterprise w ON w.id = rs.id_warehouse_enterprise
LEFT JOIN revised rd ON rd.id = rs.id_revised
LEFT JOIN (
SELECT rr.id_request, rr.id_warehouse
,array_to_string(array_agg(
DISTINCT a.name || '/' || rr.act_code), ', ') AS act_code
FROM request_reserve rr
LEFT JOIN act_code a ON r.id_act_code = a.id
GROUP BY rr.id_request, rr.id_warehouse
) rr ON rr.id_request = r.id
WHERE r.id_request_type = "any_type"; -- use single quotes for values!
For big queries it is essential that you have a format the human eye can easily parse. Therefore I reformatted before I improved the query. I use table aliases to avoid unwieldy identifiers as much as possible.
Minor improvement to create_user
: no trailing space. If either part of the name can be NULL
, I suggest this to avoid a dangling space:
COALESCE(u.name || ' ' || u.surname, u.name, u.surname)
In PostgreSQL 9.1 or later you could use concat_ws()
.