Question

I have four tables: families, parents, children, clubs. families have many parents and many children. The children have many clubs memberships.

I would like to create a "view" for fast searching names and email addresses that returns the each of the parents and children, names, email address, along with all an array of all the ids that of all the clubs that their children belong.

Here's what I have so far for the query I would like to be in the view:

 SELECT
  families.id AS family_id,
  'Child' AS searchable_type,
  concat(children.first_name, ' ',children.last_name) AS term,
  '' AS email,
  array_agg(memberships.club_id) AS clubs
FROM children
INNER JOIN families ON children.family_id = families.id
LEFT JOIN memberships ON children.id = memberships.child_id
GROUP BY families.id, term, email

UNION

SELECT
  families.id AS family_id,
  'Parent' AS searchable_type,
  concat(parents.first_name, ' ',parents.last_name) AS term,
  parents.email AS email,
  array_agg(memberships.club_id) AS clubs

FROM parents
INNER JOIN families ON parents.family_id = families.id
INNER JOIN children ON families.id = children.family_id
LEFT JOIN memberships ON children.id = memberships.child_id
GROUP BY families.id, email, term

Question's are:


Was it helpful?

Solution

Here's the answers I came up with to my initial questions, though I doubt it is the highest performance method:

  • How do I get rid of duplicate club_ids for children and parents?

Insert DISTINCT into the agg_array function

  • It's a really slow query. If it is indexed, will the view be updated every time a write happens on child or parent?

The query is slow. Creating the view is very quick. The view, as I currently understand, really provides a convenient way for doing searches. The view is not a "real" table. I think this is why making sure your are indexing all of the search terms of the view. You are not indexing the view itself.

Also, I ended up moving the email address into its own query so that became a search term as well.

Here was my final query that I based the view on:

SELECT
  families.id AS family_id,
  'Child' AS searchable_type,
  concat(children.first_name, ' ',children.last_name) AS term,
  array_agg(DISTINCT memberships.club_id) AS clubs
FROM children
INNER JOIN families ON children.family_id = families.id
LEFT JOIN memberships ON children.id = memberships.child_id
GROUP BY families.id, term

UNION

SELECT
  families.id AS family_id,
  'Parent' AS searchable_type,
  concat(parents.first_name, ' ',parents.last_name) AS term,
  array_agg(DISTINCT memberships.club_id) AS clubs

FROM parents
INNER JOIN families ON parents.family_id = families.id
INNER JOIN children ON families.id = children.family_id
LEFT JOIN memberships ON children.id = memberships.child_id
GROUP BY families.id, term

UNION

SELECT
  families.id AS family_id,
  'Parent' AS searchable_type,
  email AS term,
  array_agg(DISTINCT memberships.club_id) AS clubs

FROM parents
INNER JOIN families ON parents.family_id = families.id
INNER JOIN children ON families.id = children.family_id
LEFT JOIN memberships ON children.id = memberships.child_id
GROUP BY families.id, term
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top