2011-10-09 38 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) 
相关问题