2014-11-24 88 views
0

考虑这三个表:选择新闻,加入多个标签

新闻(专栏:身份证等)

News_Tag_Cross(列:ID,NewSID的,标签识别)

标签(专栏:身份证,姓名)

如何获得所有具有两个标签的新闻报道:“经销商”和“客户”?

我可以运行此查询的两个标签& 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' 

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

+1

放弃的表名?这有点偏执是不是?请注意,'news_tags_cross'表中的'id'似乎没有用处。 – Strawberry 2014-11-24 16:01:03

+0

安全性和简化。 PS。一个ID始终有一个目的。 – coderMe 2014-12-17 22:20:01

+0

啊,听起来像Celko说话 – Strawberry 2014-12-17 23:23:24

回答

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子句对于包含或排除的条件可以非常灵活。

+0

你可以在MSSQL中做到这一点,或者只是MySQL? 'select * from用户你有SUM(u.UserName ='XYZ')> 0'在MSSQL中引发语法 – franglais 2014-11-24 16:14:27

+0

我将t.name改为t.id,并且这个工作很好。谢谢! – coderMe 2014-11-24 16:39:22

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 

(注意大小写;它是你的描述你对代码示例不同)

+0

您的查询不会返回任何内容,因为名称列只能是一个值或其他...您需要它作为OR – DRapp 2014-11-24 16:13:20

+0

@DRapp,LOL,我已经这样做了,并在重读“and “OP的评论中的声明。当然,你是对的,我正在编辑它。 ;) – Sablefoste 2014-11-24 16:15:00

+0

我不认为一个AND或OR会工作。我需要选择新闻商品加入经销商和客户标签的位置。 OR会返回一个或另一个,对吗? – coderMe 2014-11-24 16:50:27

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' 

可能会有点长,但我会在标签上表中的索引两种方法都允许使用第一个WHERE子句,并再次使用JOIN子句。

table   indexed on 
tags   (id, name) <-- for the JOIN clause 
tags   (name) <-- for the outermost WHERE clause 
News_tag_Cross (tagID, newsID) 

澄清...说你有100,000条新闻条目,只有200个有“经销商”关键字。而不是查询整个表格和按关键字进行分组,我只是使用那些“经销商”条目开始。然后,转到news_tag_cross表,仅用于这些新闻项目并查找“客户”的辅助标记。完成。

+0

这看起来非常有趣,我不会想到创建第二个别名。在这一点上,我已经实现了我的目标,但是当我有机会时,我会用这个查询做更多的测试。 – coderMe 2014-11-24 16:47:08

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和只有在ntc.tagID则相当一段JOIN