2012-03-07 68 views
7

一個一對多的關係,我有兩個表:在(Postgre)SQL

帖子:

id | ... other stuff ... |  tags       
----+---------------------+-------------- 
    1 |   ...   | <foo><bar> 
    2 |   ...   | <foo><baz><blah> 
    3 |   ...   | <bar><blah><goo> 

和標籤:

 tag   
-------------- 
<foo> 
<bar> 
<baz> 
<blah> 
<goo> 

posts.tags和tags.tag是兩種文字類型。我要的是從tags.tag關係到行的帖子,使得查詢<foo>會給我相應的職位1和2行,查詢<blah>給了我2和3,<bar>給了我1和3等

我看過外鍵,但我不確定這是我想要的。 (說實話,我不完全確定它做了什麼)。從我可以告訴外鍵必須等於表的主鍵/唯一列。但我要的是所有行,posts.tags ~ '.*<foo>.*',等我也希望能夠,比如說,得到以b開頭的所有標籤,如:

CREATE VIEW startswithB AS 
SELECT tag 
FROM tags 
WHERE tag ~ '<b.*>'; 

SELECT DISTINCT * FROM posts, startswithB WHERE posts.tags ~ ('.*' || startswithB || '.*'); 

我如何獲得我找的關係對於?可能嗎?

編輯:

好吧,我做了什麼:

創建post_tags:

SELECT posts.id, tags.tag 
INTO post_tags 
FROM posts, tags 
WHERE posts.tags ~ ('.*' || tags.tag || '.*'); 

選擇的所有帖子與標籤<foo>

SELECT * 
FROM posts 
WHERE posts.id IN (
    SELECT id 
    FROM post_tags 
    WHERE tag = '<foo>' 
); 
+0

查找sql ['LIKE'](http://www.postgresql.org/docs/7.4/static/functions-matching.html)。在你的情況下,不可能創建一個外鍵,因爲這兩個表中的值必須匹配。 – 2012-03-07 18:14:00

+4

這種設計非常糟糕。你是否處於可以改變它的環境中?一個適當的設計將是:帖子(ID,文本,東西);標籤(id,tag);和posts_tags(post_id,tag_id),它們同時引用了帖子表和標籤表(many2many關係:標籤有很多帖子,帖子有很多標籤) – Arthur 2012-03-07 18:16:17

回答

9

你確實有什麼去這裏是一個多對多的關係。想一想:每個標籤都可以在多個帖子上,每個帖子可以有多個標籤。

這樣做的正確的關係架構是添加另一個表像這樣的中間:

CREATE TABLE post_tags (
    id INTEGER REFERENCES posts, 
    tag VARCHAR REFERENCES tags 
); 

然後在自己的帖子表中刪除tags列。

這樣可以解決您的所有問題,因爲您可以通過在不同方向上加入post_tags,從而通過給定標籤獲取帖子或帖子集中的標籤集。您還可以使用常規的LIKE查詢獲取以某些東西開頭的標籤列表,如果您在一個字段中連接了一串字符串,這將更加困難。

4

正如丹尼爾所說,你有一個多對多的關係。只是爲了澄清,這裏的所有3個表將如何看待與許多一對多設置:

帖子:

id | ... other stuff ... 
    ---+--------------------- 
    1 | ... 
    2 | ... 

標籤:

tag 
    --- 
    <foo> 
    <bar> 

Post_Tags映射表:

post_id | tag 
    --------+------ 
    1  | <foo> 
    1  | <bar> 
+0

post_id是主鍵嗎?如果是這樣,你怎麼能重複'1',因爲主鍵是'UNIQUE NOT NULL'? – dman 2016-08-24 02:58:27

4

規範化您的數據模型。這裏是代表M中的方法:N的關係,你必須:

enter image description here

請注意,POST_TAG的PK是{POST_ID,TAG},不只是{} POST_ID。

找到標有「富」的所有帖子應該是這樣的:

SELECT * 
FROM POST 
WHERE 
    POST_ID IN (
     SELECT POST_ID 
     FROM POST_TAG 
     WHERE TAG = 'foo' 
    ) 

對於標有與「F」開頭的標籤的帖子,你可以這樣做:

SELECT * 
FROM POST 
WHERE 
    POST_ID IN (
     SELECT POST_ID 
     FROM POST_TAG 
     WHERE TAG LIKE 'f%' 
    )