SELECT匹配多个WHERE标准(来自链接表)

时间:2017-02-21 18:28:15

标签: mysql sql

我可能会遗漏一些明显的东西,但我需要一个只返回同一列上符合多个条件的记录的查询。

该表是一个简单的链接表,可以将标签链接到照片,即标签可以应用于多张照片,而照片可以有多个标签。

photoid | tagid
----------------
 343    |    2
 343    |    5
 343    |    8
 522    |    5
 522    |    1
 522    |   10
 522    |    8
 118    |    8
 118    |    5
etc...

如图所示,photoid 343有3个标签。

现在,我需要的是一个查询,它为所有具有特定标签的照片提供了photoid。照片应该 tagid 1 tagid 2,并且两个 tagid 5 tagid 8,但是必须有tagid 10。  即就像是 (tagid=1 OR tagid=2) AND (tagid=5 AND tagid=8) AND tagid!=10。 在上面的示例中,只有343匹配。

我使用WHERE INGROUP BY

尝试了HAVING COUNT
SELECT PhotoTags.photoid, FROM PhotoTags
WHERE (PhotoTags.tagid) IN ((5),(8)) AND (PhotoTags.tagid) NOT IN (10)
GROUP BY PhotoTags.photoid
HAVING count(distinct PhotoTags.tagid)=2

这只是工作的一部分,它为我提供了所有匹配tagid 5和8但不匹配10的照片。如何在查询中添加AND (tagid=1 OR tagid=2)条件?

3 个答案:

答案 0 :(得分:0)

我不知道这是否是最佳解决方案,但似乎有效。您可以使用GROUP_CONCAT列出图片的所有标记,然后您可以使用HAVING根据该值中的内容进行过滤。

SELECT photoid, GROUP_CONCAT(tagid ORDER BY tagid ASC) AS tags
FROM PhotoTags
GROUP BY photoid DESC
HAVING tags RLIKE '(^|,)5,.*8(,|$)'
AND tags NOT RLIKE '(^|,)10(,|$)';

您也可以尝试使用FIND_IN_SET代替正则表达式(RLIKE):

SELECT photoid, GROUP_CONCAT(tagid ORDER BY tagid ASC) AS tags
FROM PhotoTags
GROUP BY photoid DESC
HAVING FIND_IN_SET(5, tags) AND FIND_IN_SET(8, tags)
AND NOT FIND_IN_SET(10, tags);

编辑:如果您想添加OR子句,请尝试以下操作:

SELECT photoid, GROUP_CONCAT(tagid ORDER BY tagid ASC) AS tags
FROM PhotoTags
GROUP BY photoid DESC
HAVING (FIND_IN_SET(1, tags) OR FIND_IN_SET(2, tags))
AND FIND_IN_SET(5, tags) AND FIND_IN_SET(8, tags)
AND NOT FIND_IN_SET(10, tags);

答案 1 :(得分:0)

如果你这样做

WHERE (PhotoTags.tagid) IN ((5),(8)) AND (PhotoTags.tagid) NOT IN (10)

此AND不会被考虑因为已经检查tagId是否为5或8

AND (PhotoTags.tagid) NOT IN (10)

IN只能用逗号分隔值,记住AND优先于OR,尝试这个并检查它是否给你想要的结果,它只会选择5或8或1或2的tagid < / p>

SELECT PhotoTags.photoid, FROM PhotoTags
WHERE (PhotoTags.tagid) IN (5,8,1,2)
GROUP BY PhotoTags.photoid
HAVING count(distinct PhotoTags.tagid)=2

答案 2 :(得分:0)

好像你想要找到所有照片:

  • 至少有一个标签(1,2)
  • 有标签10
  • 标签(5,8)

第一个要求可以使用IN子句和SELECT DISTINCT轻松处理。

第二个要求可能最好使用NOT EXISTS处理。

可以通过多种方式处理第三项要求:使用子查询,NOT EXISTSGROUP BY / HAVING等。我将使用子查询给您一个示例,但是这可能不适合您,特别是如果所需标签的数量不总是2。

希望这可以让您开始寻找适合您的解决方案的正确途径:

 select distinct t1.photoid 
 from PhotoTags t1
   inner join (
     select distinct photoid 
     from PhotoTags 
     where tagid = 5
   ) t2 on t2.photoid = t1.photoid
   inner join (
     select distinct photoid 
     from PhotoTags 
     where tagid = 8
   ) t3 on t3.photoid = t1.photoid 
 where t1.tagid in (1,2)
   and not exists (
     select NULL 
     from PhotoTags t4
     where t4.photoid = t1.photoid
     and t4.tagid = 10
)