2011-10-09 47 views
1

我有一個名爲content的mysql表,它存儲內容管理系統的內容數據。MySQL查詢 - 使用URL名稱將數據組織到一個層次中使用URL名稱的數據

注意:所有內容都使用父級ID列組織成層級。

+----+------------+-----------------+--------+ 
| id | slug  | content_type_id | parent | 
+----+------------+-----------------+--------+ 
| 1 | portfolio |    5 |  0 | 
| 2 | about-us |    1 |  0 | 
| 3 | find-us |    1 |  0 | 
| 4 | contact-us |    1 |  2 | 
| 5 | find-us |    1 |  4 | 
+----+------------+-----------------+--------+ 

我需要一個查詢來選擇表中正確的行,這取決於slug名稱是什麼。問題是slu have有相同的名字。

我有兩個可能的路徑,其用戶可以訪問:

/find-us/ 

/about-us/contact-us/find-us/ 

我能想到一個解決方案:

這與創建另一列全路徑:

full_path 
-------- 
/portfolio/ 
/about-us/ 
/find-us/ 
/about-us/contact-us/ 
/about-us/contact-us/find-us/ 

但是有什麼聰明的方法可以用來選擇正確的行。我不確定創建具有完整路徑名的另一列是否是一個非常好的主意(因爲這些主題有改變的潛力),我個人只希望將其作爲最後的手段。

謝謝。

+0

IIRC MySQL不允許遞歸查詢? – wildplasser

+1

完整的路徑是你必須知道無論如何知道你正在服務哪個頁面的權利?所以它看起來像你可能想要維護的東西,所以對於我來說,這個問題可能不是「我想維護它嗎?」,而是「我該如何維護它?」,我認爲正確的答案是這是通過觸發器。 – briantyler

+0

是wildplasser,你是對的遞歸查詢是不可能的。 B泰勒 - 這是一個有趣的想法,我會考慮。 – sidewinder

回答

-1

如果你的DBMS所支持的遞歸查詢這將是可能的:

DROP SCHEMA tmp CASCADE; 
CREATE SCHEMA tmp ; 

CREATE TABLE tmp.webmeuk 
    (id INTEGER NOT NULL PRIMARY KEY 
    , slug VARCHAR 
    , content_type_id INTEGER NOT NULL 
    , parent_id INTEGER REFERENCES tmp.webmeuk(id) 
    ); 
INSERT INTO tmp.webmeuk(id , slug, content_type_id , parent_id) 
VALUES( 0 , 'HTTP://pr0n.mysite.xx', 5 , NULL) 
    , ( 1 , 'portfolio', 5 , 0) 
    , ( 2 , 'about-us', 1 , 0) 
    , ( 3 , 'find-us',  1 , 0) 
    , ( 4 , 'contact-us', 1 , 2) 
    , ( 5 , 'find-us',  1 , 4) 
    ; 

-- a room with a view 
CREATE VIEW tmp.reteview AS (
    WITH RECURSIVE xx AS (
     SELECT w0.id AS id 
     , w0.slug AS slug 
     , w0.content_type_id AS content_type_id 
     , w0.slug AS fullpath 
     FROM tmp.webmeuk w0 
     WHERE w0.parent_id IS NULL 
     UNION 
     SELECT w1.id AS id 
     , w1.slug AS slug 
     , w1.content_type_id AS content_type_id 
     , xx.fullpath || '/'::text || w1.slug AS fullpath 
     FROM tmp.webmeuk w1, xx 
     WHERE w1.parent_id = xx.id 
     ) 
    SELECT * FROM xx 
    ); 

SELECT * FROM tmp.reteview ; 

-- Change one row of data 
UPDATE tmp.webmeuk 
SET slug = 'what-about-us' 
WHERE id = 2; 

SELECT * FROM tmp.reteview ; 

輸出:

NOTICE: drop cascades to 2 other objects 
DETAIL: drop cascades to table tmp.webmeuk 
drop cascades to view tmp.closure 
DROP SCHEMA 
CREATE SCHEMA 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "webmeuk_pkey" for table "webmeuk" 
CREATE TABLE 
INSERT 0 6 
CREATE VIEW 
id |   slug   | content_type_id |      fullpath     
----+-----------------------+-----------------+--------------------------------------------------- 
    0 | HTTP://pr0n.mysite.xx |    5 | HTTP://pr0n.mysite.xx 
    1 | portfolio    |    5 | HTTP://pr0n.mysite.xx/portfolio 
    2 | about-us    |    1 | HTTP://pr0n.mysite.xx/about-us 
    3 | find-us    |    1 | HTTP://pr0n.mysite.xx/find-us 
    4 | contact-us   |    1 | HTTP://pr0n.mysite.xx/about-us/contact-us 
    5 | find-us    |    1 | HTTP://pr0n.mysite.xx/about-us/contact-us/find-us 
(6 rows) 

UPDATE 1 
id |   slug   | content_type_id |      fullpath      
----+-----------------------+-----------------+-------------------------------------------------------- 
    0 | HTTP://pr0n.mysite.xx |    5 | HTTP://pr0n.mysite.xx 
    1 | portfolio    |    5 | HTTP://pr0n.mysite.xx/portfolio 
    3 | find-us    |    1 | HTTP://pr0n.mysite.xx/find-us 
    2 | what-about-us   |    1 | HTTP://pr0n.mysite.xx/what-about-us 
    4 | contact-us   |    1 | HTTP://pr0n.mysite.xx/what-about-us/contact-us 
    5 | find-us    |    1 | HTTP://pr0n.mysite.xx/what-about-us/contact-us/find-us 
(6 rows) 
相關問題