Reputation: 742
I've got relation between 3 tables, let's call them tree
, parent
and children
.
I want to (always) fetch tree, fetch parent if it's not deleted or has undeleted children and children if they're not deleted.
Following query works with exception that it doesn't fetch the tree.
SELECT *
FROM tree t
LEFT JOIN parent p ON t.id = p.tree_id
LEFT JOIN children c ON p.id = c.parent_id
WHERE t.id = 2599
AND (p.deleted = false OR (p.deleted = true AND pc.deleted = false));
Any ideas?
Upvotes: 0
Views: 61
Reputation: 94913
It is actually not that difficult. (EDIT: I wish I had never said this ;-) Only make sure to treat outer joined records correctly (i.e. check for null).
SELECT *
FROM tree t
LEFT JOIN parent p ON t.id = p.tree_id
LEFT JOIN children c ON p.id = c.parent_id and c.deleted = false
WHERE t.id = 2599
AND (p.id is null OR p.deleted = false OR c.deleted = false) -- parent okay?
AND (c.id is null OR c.deleted = false) -- child okay?
Upvotes: 0
Reputation: 86735
As mentioned in the comments, it looks like you're got a problem in the second join.
Also, your WHERE
clause is going to turn those LEFT JOIN
s in to INNER JOIN
s:
- NULL
is never equal to either TRUE or FALSE
I'd try something like this...
SELECT
*
FROM
tree AS t
LEFT JOIN
(
parent AS p
LEFT JOIN
children AS c
ON c.parent_id = p.id
AND c.deleted = false
)
ON (t.id = p.tree_id)
AND (c.id IS NOT NULL OR p.deleted = false)
WHERE
t.id = 2599
children
only get associated to parent
is they're not deleted.
That join only gets associated to tree
if parent
is not deleted, or there are children (we've already ensured that they're only included if they're not deleted).
EDIT :
I never like using RIGHT JOIN
, but perhaps it could be more readable with it? I don't think so, but I'll include it for completeness.
SELECT
*
FROM
parent AS p
LEFT JOIN
children AS c
ON c.parent_id = p.id
AND c.deleted = false
RIGHT JOIN
tree AS t
ON (t.id = p.tree_id)
AND (c.id IS NOT NULL OR p.deleted = false)
WHERE
t.id = 2599
Upvotes: 1