选择新闻,加入多个标签

时间:2014-11-24 15:59:02

标签: mysql sql

考虑这三个表:

新闻(列: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'

我必须注意,这是我当前查询的粗略翻译 - 我真的不想放弃表名等,或者将任何人与额外的列和数据混淆。

4 个答案:

答案 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