SELECT 'person' AS type, person.id, person.name, CASE person.active WHEN true THEN 'Active' WHEN false THEN 'Inactive' END || ', In group(s): '||array_to_string(array_agg(pgroup.name), ',') AS desc, person.fts 
FROM person,membership,pgroup 
WHERE person.id = membership.person 
	AND membership.pgroup = pgroup.id 
GROUP BY person.id, person.name, person.fts, person.active

UNION 

SELECT 'pgroup' AS type, pgroup.id, pgroup.name, '' AS desc, pgroup.fts
FROM pgroup 

UNION

SELECT 'image' AS type, image.id, image.name, image.info AS desc, image.fts
FROM image

UNION

SELECT 'folder' AS type, folder.id, folder.name, count(exercise.id)::text || ' exercise(s)' AS desc, folder.fts
FROM folder LEFT OUTER JOIN exercise ON exercise.folder = folder.id
GROUP BY folder.id, folder.name, folder.fts

UNION

SELECT 'exercise' AS type, exercise.id, exercise.name, exercise.description AS desc, exercise.fts
FROM exercise

