Created
April 6, 2012 13:50
-
-
Save temoto/2319942 to your computer and use it in GitHub Desktop.
plpgsql for loop -> single select?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Types: ticket_query, ticket_result | |
-- Functions: ticket_search_1, ticket_unique_sellers | |
drop type ticket_query cascade; | |
create type ticket_query as ( | |
cities_from text[], | |
cities_to text[], | |
date_direct date, | |
date_back_min date, | |
date_back_max date, | |
expires timestamp(0) without time zone, | |
modified timestamp(0) without time zone, | |
adults smallint, | |
children smallint, | |
infants smallint, | |
sellers_1_adult smallint[], | |
limit_filter smallint | |
); | |
create type ticket_result as ( | |
id uuid, | |
adults smallint, | |
children smallint, | |
infants smallint, | |
seller smallint, | |
city_from char(3), | |
city_to char(3), | |
date_direct date, | |
date_back date, | |
cost integer, | |
expires timestamp(0) without time zone, | |
url text, | |
modified timestamp(0) without time zone, | |
seller_data bytea, | |
data bytea | |
); | |
create or replace function ticket_search_1(q ticket_query) returns setof ticket_result as $$ | |
declare | |
s text; | |
suffix text; | |
begin | |
suffix := replace(q.date_direct::text, '-', '_'); | |
-- for s in | |
-- execute 'explain analyze select distinct on (id) q1.* | |
return query execute 'select distinct on (id) q1.* | |
from ( | |
select ticket.id, $7, $8, $9, seller, | |
ticket.city_from, ticket.city_to, ticket.date_direct, ticket.date_back, cost, | |
ticket.expires, url, modified, seller_data, route.data | |
from ticket_' || suffix || ' as ticket, route_' || suffix || ' as route | |
where ticket.id = route.id | |
and ' || (case when array_length(q.cities_from, 1) = 1 then 'ticket.city_from = $1[1]' | |
else 'ticket.city_from = any($1)' | |
end) || ' | |
and ' || (case when array_length(q.cities_to, 1) = 1 then 'ticket.city_to = $2[1]' | |
else 'ticket.city_to = any($2)' | |
end) || ' | |
and ' || (case when q.date_back_min is null then 'ticket.date_back is null' | |
else 'ticket.date_back between $3 and $4' | |
end) || ' | |
and ($5 is null or ticket.expires >= $5) | |
and ($6 is null or ticket.modified > $6) | |
and (case when seller = any($10) then (adults = 1 and children = 0 and infants = 0) | |
else (adults = $7 and children = $8 and infants = $9) | |
end) | |
order by cost | |
limit $11 | |
) as q1 | |
order by id, cost' using q.cities_from, q.cities_to, q.date_back_min, q.date_back_max, q.expires, | |
q.modified, q.adults, q.children, q.infants, q.sellers_1_adult, q.limit_filter, suffix | |
; | |
-- loop | |
-- raise notice '%', s; | |
-- end loop; | |
end; | |
$$ language 'plpgsql'; | |
create or replace function ticket_search_2(direct_dates date[], base_query ticket_query) returns setof ticket_result as $$ | |
declare | |
d date; | |
q ticket_query; | |
begin | |
for d in (select * from unnest(direct_dates)) loop | |
q = base_query; | |
q.date_direct = d; | |
return query select * from ticket_search_1(q); | |
end loop; | |
end; | |
$$ language 'plpgsql'; | |
create or replace function search_2(direct_dates date[], base_query query) returns setof result as $$ | |
declare | |
d date; | |
q query; | |
begin | |
for d in (select * from unnest(direct_dates)) loop | |
q = base_query; | |
q.date_direct = d; | |
return query select * from search_1(q); | |
end loop; | |
end; | |
$$ language 'plpgsql'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment