我有三个表:文章,标签和articles_tags(交汇点)。
在tags
内我有3个(相关)列:
id
,name
和alias
。
alias
列包含早期同义标记的ID(如果存在)(否则为NULL
)。 没有循环或链:所有同义标记都包含相同的别名。例如:
tags
id | name | alias
------------------------------------
------------------------------------
8 | pencil | NULL
------------------------------------
------------------------------------
3072 | pencils | 8
------------------------------------
------------------------------------
3073 | blue pencil| 8
------------------------------------
(标签必须具有此功能,因为它们是用户输入的。)
现在,我们想要搜索包含标记pencils
或cats
的所有文章。我希望他们包含所有其他同义标签(铅笔,蓝色铅笔, tomcat ,小猫等。)。
我提出的查询如下:
SELECT * FROM `articles` WHERE id IN
(SELECT article_id FROM `articles_tags` WHERE id IN
(SELECT id FROM `tags` WHERE COALESCE(alias, id) IN
(SELECT id FROM `tags` WHERE name IN
("pencils", "cats")
)
)
)
我相信它有效,但我认为使用 IN 的4个子查询可能有更好的方法(性能是关键,因为这将是常见的搜索)。
我非常感谢为更好的解决方案提供指导。
感谢。
如果我需要查找不包含其他标签的文章,那该怎么办?
即,选择所有仅包含标签的文章" cats"和#34;狗"将返回唯一标签为("猫"),("狗")或("猫","狗")的文章
编辑:表格结构:
id | name | alias
------------------------------------
...
------------------------------------
8 | pencil | NULL
------------------------------------
...
------------------------------------
3072 | pencils | 8 (pencil)
------------------------------------
------------------------------------
3073 | blue pencil| 8 (pencil)
------------------------------------
------------------------------------
6088 | cats | NULL
------------------------------------
------------------------------------
7098 | dogs | NULL
------------------------------------
------------------------------------
7099 | kittens | 6088 (cats)
------------------------------------
------------------------------------
7102 | chiwawa | 7098 (dogs)
------------------------------------
id | title | content
----------------------------------------
...
----------------------------------------
1 | I love writing | ...
----------------------------------------
...
----------------------------------------
42 |Tips for pet owners | ...
----------------------------------------
----------------------------------------
108 | Drawing my dog | ...
----------------------------------------
id | article_id | tag_id
------------------------------------
...
------------------------------------
19 | 1(I love writing) | 3072 (pencils)
------------------------------------
------------------------------------
21 | 1(I love writing) | 3010 (poetry)
------------------------------------
------------------------------------
22 | 1(I love writing) | 123 (books)
------------------------------------
------------------------------------
34 | 42(Tips for pet ...) | 6088 (cats)
------------------------------------
------------------------------------
35 | 42(Tips for pet ...) | 7098 (dogs)
------------------------------------
...
------------------------------------
78 | 108(Drawing my dog) | 7098 (dogs)
------------------------------------
------------------------------------
78 | 108(Drawing my dog) | 8 (pencil)
------------------------------------
所需的输出:
正在搜索chiwawa
,cats
会产生"宠物主人提示","吸引我的狗"。
搜索pencil
,dogs
应该会产生"我喜欢写作","画我的狗"。
对于第二个(奖金)部分:
搜索chiwawa
,kittens
应该会产生仅"宠物主人提示"和不"绘制我的狗"因为它还有一个pencils
标记。
抱歉文字数量。
答案 0 :(得分:1)
您可以通过以下方式获取文章ID:
select ata.article_id
from articles_tags ata join
tags t
on ata.tag_id = t.id
where t.name in ('pencil', 'cats')
group by ata.article_id
having count(distinct t.name) = 2;
对于第二个问题,您可以使用条件聚合。这是一种方法:
select ata.article_id
from articles_tags ata join
tags t
on ata.tag_id = t.id
where t.name in ('pencil', 'cats')
group by ata.article_id
having sum(t.name = 'pencil') > 0 and sum(t.name = 'cats') > 0;
如果您需要,可以加入articles
以获取其他列。
答案 1 :(得分:1)
你在这里基本上有两个问题......第一个是关系部门 - 选择适用于父记录的标签,这本身可能会有点乐趣。以下是两个相关链接:
https://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/(Celko)
这个问题的答案提供了大约十几种不同的查询方式(以及使用PostgreSQL的性能基准)。信息量很大:
How to filter SQL results in a has-many-through relation
至于#34;铅笔与铅笔"类型标签,我建议通过输入应用程序处理这个。创建一个"过滤器"将标签映射到其他固有标签的种类。所以,当有人输入"铅笔"标签,它自动a)过滤到"铅笔",或b)输入铅笔和铅笔。这对像"蓝色铅笔"这样的东西特别有用。鉴于如上所述的关系划分问题的相对复杂性,我认为如果"蓝色铅笔"那么你会发现自己更容易管理数据模型。添加了"铅笔"和"蓝色铅笔" (也许" blue")标记到数据库中。
在某一点上,逻辑应成为应用程序域的一部分并远离数据库。我相信这是一个很好的例子。否则,你可能会冒险尝试将数据库引擎强制转换为它真正没有设计的东西,这根本就没什么乐趣。