Apologies for the terrible question title, I couldn't think how to describe this question in a single line.
I have a schema that looks roughly like this: https://dbdiagram.io/d/6595820aac844320ae2df56f
Image may be NSFW.
Clik here to view.
Both people and organisations can list a set of requirements. People and organisations can be connected to each other.
For a given organisation I want to count how many requirements listed by the connected people are also listed by the organisation.
For example, maybe the requirements are allergens. If a person lists an allergen it means they can't eat that food, if an organisation lists an allergen it means their kitchen can provide food that does not contain that allergen. So the question is, for a given organisation, how many times are people experiencing an allergen that the org can deal with.
The complexity (to my mind) comes from the fact that organisations can have parent/child relationships. If a requirement is listed on a parent org, then it is also "listed" for all descendents. If a person is connected to a child org, then they are "connected" to all ancestors too.
In the example, if a parent org can cope with an allergen then so can all the child orgs (maybe the head chef does training for all the connected kitchens??). And if a person eats at a child kitchen then that counts as them eating at all the parent kitchens too.
I've got other queries where I'm using recursive CTEs to follow the organisation relationships. But this one is more than I can handle because of the connections to the people.
My best attempt so far is:
WITH RECURSIVE tree1 (id, parent_id) AS ( SELECT id, parent_id FROM organisations WHERE id = :org_id UNION ALL SELECT tree2.id, tree2.parent_id FROM organisations AS tree2 JOIN tree1 ON tree1.id = tree2.parent_id)SELECT COUNT(*)FROM person_requirements AS prWHERE pr.person_id IN ( SELECT c.person_id FROM connections AS c WHERE c.organisation_id IN (SELECT id FROM tree1))AND pr.requirement_id IN ( SELECT or.requirement_id FROM organisation_requirements AS or WHERE or.organisation_id IN (SELECT id FROM tree1))
But this is wrong because if a sibling org lists a requirement it gets counted even if the org that connects to the person doesn't list it.
I suspect that the solution might be to change the CTE so that it returns a list of orgs and its requirements? But I wasn't sure how to do that recursively.
Thanks for your help!