2015-10-19 76 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」完成的。