BEGIN; CREATE TYPE langprefs AS ( t1_lang language, -- NULL for original language t2_lang language, t3_lang language, t4_lang language, t5_lang language, t1_latin boolean, t2_latin boolean, t3_latin boolean, t4_latin boolean, t5_latin boolean, t1_official boolean, -- always true for original language t2_official boolean, t3_official boolean, t4_official boolean, t5_official boolean ); CREATE TYPE vntitle_state AS ( rank smallint, title text ); CREATE OR REPLACE FUNCTION vntitle_sfunc(state vntitle_state, t vn_titles, olang language, p langprefs) RETURNS vntitle_state AS $$ BEGIN IF state.rank > 1 AND COALESCE(p.t1_lang, olang) = t.lang AND (NOT p.t1_official OR t.official) THEN RETURN ROW(1::smallint, COALESCE(CASE WHEN p.t1_latin THEN t.latin ELSE NULL END, t.title)); ELSIF state.rank > 2 AND COALESCE(p.t2_lang, olang) = t.lang AND (NOT p.t2_official OR t.official) THEN RETURN ROW(2::smallint, COALESCE(CASE WHEN p.t2_latin THEN t.latin ELSE NULL END, t.title)); ELSIF state.rank > 3 AND COALESCE(p.t3_lang, olang) = t.lang AND (NOT p.t3_official OR t.official) THEN RETURN ROW(3::smallint, COALESCE(CASE WHEN p.t3_latin THEN t.latin ELSE NULL END, t.title)); ELSIF state.rank > 4 AND COALESCE(p.t4_lang, olang) = t.lang AND (NOT p.t4_official OR t.official) THEN RETURN ROW(4::smallint, COALESCE(CASE WHEN p.t4_latin THEN t.latin ELSE NULL END, t.title)); ELSIF state.rank > 5 AND COALESCE(p.t5_lang, olang) = t.lang AND (NOT p.t5_official OR t.official) THEN RETURN ROW(5::smallint, COALESCE(CASE WHEN p.t5_latin THEN t.latin ELSE NULL END, t.title)); END IF; RETURN state; END; $$ LANGUAGE plpgsql IMMUTABLE; CREATE OR REPLACE AGGREGATE vntitle(vn_titles, language, langprefs) ( SFUNC = vntitle_sfunc, STYPE = vntitle_state, INITCOND = '(6,)' ); SET max_parallel_workers_per_gather = 0; EXPLAIN ANALYZE SELECT v.id, vntitle(t, v.olang, '(en,,,,,f,f,f,f,f,f,f,f,f,f)'::langprefs) title FROM vn v JOIN vn_titles t ON t.id = v.id WHERE NOT hidden --AND v.id < 'v10' GROUP BY v.id ORDER BY title LIMIT 100; EXPLAIN ANALYZE SELECT v.id, max(t.title) as title FROM vn v JOIN vn_titles t ON t.id = v.id WHERE NOT hidden --AND v.id < 'v10' GROUP BY v.id ORDER BY title LIMIT 100;