考虑这三个表:
新闻(列:ID等)
News_Tag_Cross (列:ID,新闻ID,TagID)
标记(列:ID,名称)
我如何获得所有包含两个标签的新闻文章:“经销商”和“客户”?
我可以为这两个标签运行此查询UNION结果,但返回经销商标记或客户端标记的行。显然,我想返回加入两者的新闻项目。
SELECT n.id FROM news
INNER JOIN news_tag_cross ntc
ON ntc.newsid=n.id
INNER JOIN tags t
ON t.id=ntc.tagid
WHERE news_tag_cross.tagID = 'DealerID'
我必须注意,这是我当前查询的粗略翻译 - 我真的不想放弃表名等,或者将任何人与额外的列和数据混淆。
答案 0 :(得分:1)
您可以将聚合与having
子句一起使用:
SELECT n.id
FROM news INNER JOIN
news_tag_cross ntc
ON ntc.newsid = n.id INNER JOIN
tags t
ON t.id = ntc.tagid
GROUP BY n.id
HAVING SUM(t.name = 'Dealer') > 0 AND
SUM(t.name = 'Client') > 0;
还有其他表达方式(特别是使用连接)。我喜欢这种方法,因为having
子句在包含或排除条件方面非常灵活。
答案 1 :(得分:0)
一个简单的子查询怎么样:
SELECT news.* FROM news WHERE id =
(SELECT NewsID FROM news_tag_cross
JOIN tags ON news_tag_cross.tagid=tags.id
WHERE tags.Name="Dealer" OR tabs.Name="Clients"
) AS tbl
(注意大小写;在您的描述与代码示例中有所不同)
答案 2 :(得分:0)
我对这种类型的查询的方法是通过连接来完成,但是在一个条件上有第一个WHERE子句,在第二个条件上有连接。通过这种方式,您不会查找所有新闻ID条目,如果他们没有东西就把它们扔掉......
select
n.*
from
tags t
JOIN News_Tag_Cross ntc
on t.id = ntc.TagID
JOIN News_tag_Cross ntc2
on ntc.NewsID = ntc2.NewsID
Join Tags t2
on ntc2.tagID = t2.id
AND t2.Name = 'Client'
JOIN News n
on ntc.NewsID = n.ID
where
t.name = 'Dealer'
可能会长一点,但我会在tags表上有一个索引,允许第一个WHERE子句和JOIN子句。
table indexed on
tags (id, name) <-- for the JOIN clause
tags (name) <-- for the outermost WHERE clause
News_tag_Cross (tagID, newsID)
澄清...说你有10万条新闻条目,只有200条有“经销商”关键字。我没有查询整个表格并按关键字进行分组,而是仅使用那些“经销商”条目启动。从那里,仅针对那些新闻项目转到news_tag_cross表并查找“客户”的辅助标签。完成。
答案 3 :(得分:0)
您忘了news
来命名
SELECT n.id FROM news n
INNER JOIN news_tag_cross ntc
ON ntc.newsid=n.id
INNER JOIN tags t
ON t.id=ntc.tagid
WHERE ntc.tagID = 'DealerID'
但仅在n.id和WHERE中仅在ntc.tagID中选择,然后是一段JOIN