循环记录及其父母查找匹配记录

时间:2015-10-19 22:57:07

标签: sql postgresql

我有这三个表:

items

id   parent_id
--------------
590  589
589  588
588  587
587  586

user_items

item_id   project_id   user_id
------------------------------
588       50           2
587       49           2

users

id
--
2

我需要找到user_item,其item_id与项目的id或项目的parent_id匹配。它还需要匹配user_id。

这是应该的方式:

1)从item_id 590和user_id 2开始,我查询user_items表。没有记录。

2)我查询id为590的项目,找到项目的parent_id,即589.然后我取出parent_id和user_id,再次查询user_items表。没有记录。

3)然后我找到id为589的项记录。我使用该记录的parent_id(588)并再次查询user_items表。有一个匹配,所以它打破了循环并返回匹配的user_item。

请注意,我必须使用此架构,并且需要返回匹配的第一个user_item。最多可以有5个级别的项目及其父母。

起初我以为我可以使用项目590及其所有父项,但这会选择太多的user_items。它需要返回匹配的最低级别项。我还以为我可以使用循环,但我不熟悉它是如何工作的,我想有一个更简单的解决方案。

思想?

2 个答案:

答案 0 :(得分:1)

使用Postgresql,您将需要使用所谓的CTE或公用表表达式。以下是我希望有用的片段。

WITH RECURSIVE t(id, parent_id, path) AS (
    SELECT id, parent_id, ARRAY[id]
    FROM items
    WHERE id = 590
  UNION
    SELECT i.id, i.parent_id, i.parent_id || t.path
    FROM items i
    INNER JOIN t ON t.parent_id = i.id
)
SELECT items.* FROM items
INNER JOIN t ON t.id = items.id
INNER JOIN user_items ON user_items.item_id = items.id AND user_items.user_id = 2

答案 1 :(得分:0)

您需要使用递归来避免需要循环。我会在这篇postgresql文章中阅读“with recursive”选项:http://www.postgresql.org/docs/9.4/static/queries-with.html

使用递归将所有项目/父项目连接在一起后,您可以将结果限制为仅获得具有用户ID的项目。

作为旁注,Oracle中的递归是通过使用关键字“start with”和“connect by”来完成的。