我有两张桌子:
帖子:
id | ... other stuff ... | tags
----+---------------------+--------------
1 | ... | <foo><bar>
2 | ... | <foo><baz><blah>
3 | ... | <bar><blah><goo>
Run Code Online (Sandbox Code Playgroud)
和标签:
tag
--------------
<foo>
<bar>
<baz>
<blah>
<goo>
Run Code Online (Sandbox Code Playgroud)
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 || '.*');
Run Code Online (Sandbox Code Playgroud)
我如何获得我正在寻找的关系?可能吗?
编辑:
好的,我做了什么:
创建post_tags:
SELECT posts.id, tags.tag
INTO post_tags
FROM posts, tags
WHERE posts.tags ~ ('.*' || tags.tag || '.*');
Run Code Online (Sandbox Code Playgroud)
选择所有带标签的帖子<foo>:
SELECT *
FROM posts
WHERE posts.id IN (
SELECT id
FROM post_tags
WHERE tag = '<foo>'
);
Run Code Online (Sandbox Code Playgroud)
你实际上在这里发生的是多对多的关系.想一想:每个标签可以在几个帖子上,每个帖子可以有几个标签.
正确的关系架构是在中间添加另一个表,如下所示:
CREATE TABLE post_tags (
id INTEGER REFERENCES posts,
tag VARCHAR REFERENCES tags
);
Run Code Online (Sandbox Code Playgroud)
然后将tags列放在posts表上.
这解决了您的所有问题,因为您可以通过在不同方向上与post_tags连接,在帖子或具有给定标签的帖子集上获取标签集.您还可以使用常规LIKE查询获取以某些内容开头的标记列表,如果您在一个字段中连接了一堆字符串,则会更加困难.
小智 5
正如丹尼尔提到的,你们之间存在多对多关系。为了澄清起见,以下是所有 3 个表在多对多设置下的外观:
帖子:
id | ... other stuff ...
---+---------------------
1 | ...
2 | ...
Run Code Online (Sandbox Code Playgroud)
标签:
tag
---
<foo>
<bar>
Run Code Online (Sandbox Code Playgroud)
Post_Tags映射表:
post_id | tag
--------+------
1 | <foo>
1 | <bar>
Run Code Online (Sandbox Code Playgroud)