获取过滤后的树状关系

时间:2014-05-19 11:01:01

标签: sql postgresql

我有3个表之间的关系,我们称之为treeparentchildren

我想(总是)获取树,如果没有删除则获取父级,或者如果未删除,则删除未删除的子级和子级。

以下查询使用异常,它不会获取树。

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));

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

正如评论中所提到的,看起来你在第二次加入时遇到了问题。

此外,您的WHERE子句会将LEFT JOIN转换为INNER JOIN s:
- NULL永远不会等于TRUE或FALSE

我会尝试这样的事情......

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仅与parent相关联,因为它们未被删除。

如果tree未被删除,或者有子女(我们已经确保只有在未删除时才包含这些内容),该加入才会与parent相关联

编辑:

我从不喜欢使用RIGHT JOIN,但也许它可以更具可读性?我不这么认为,但我会把它包括在内以便完整。

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 

答案 1 :(得分:0)

实际上并不困难。 (编辑:我希望我从来没有说过这个;-)只确保正确处理外连接记录(即检查为空)。

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?