2015-10-19 46 views
0

我有这三个表:遍历记录和他们的父母找到匹配的记录

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 

我需要找到其ITEM_ID要么匹配的项目的ID或项目的PARENT_ID的user_item。它也需要匹配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。它需要返回匹配的最低级别的项目。我也认为我可以使用循环,但我不熟悉这是如何工作的,我想有一个更简单的解决方案。

想法?

回答

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 
0

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

一旦使用递归将所有项目/父项目连接在一起,就可以将结果限制为仅使用用​​户标识获得结果。

作为一个方面说明,Oracle中的递归是通过使用关键字“start with”和“connect by”完成的。