Mysql 选择匹配多个WHERE准则(从链接表)

Mysql 选择匹配多个WHERE准则(从链接表),mysql,sql,Mysql,Sql,我可能遗漏了一些明显的内容,但我需要一个只返回与同一列上的多个条件匹配的记录的查询 该表是一个简单的链接表,将标签链接到照片,即一个标签可以应用于多张照片,一张照片可以有多个标签 photoid | tagid ---------------- 343 | 2 343 | 5 343 | 8 522 | 5 522 | 1 522 | 10 522 | 8 118 | 8 118

我可能遗漏了一些明显的内容,但我需要一个只返回与同一列上的多个条件匹配的记录的查询

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

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或tagid=2)和(tagid=5和tagid=8)以及tagid=10
。 在上面的示例中,只有343个匹配

我试过使用
WHERE IN
groupby
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

这只做了部分工作,它给了我所有的照片匹配Tagid5和8,但不是10。如何将
和(tagid=1或tagid=2)
条件添加到查询中?

我不知道这是否是最好的解决方案,但似乎有效。您可以使用
GROUP\u 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
而不是regex(
RLIKE
):


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

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);
如果你这样做

WHERE (PhotoTags.tagid) IN ((5),(8)) AND (PhotoTags.tagid) NOT IN (10)
这将不被考虑,因为正在检查tagId是5还是8

AND (PhotoTags.tagid) NOT IN (10)
在只能使用逗号分隔的值中,请记住,并且优先于OR,尝试此操作并检查它是否提供了所需的结果,它将只选择5或8或1或2的tagid

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

您似乎希望找到所有以下照片:

  • 至少有一个标签(1,2)
  • 没有标签10
  • 具有两个标签(5,8)
第一个需求可以通过
IN
子句和
选择DISTINCT
轻松处理

第二个需求最好使用
不存在
来处理

第三个要求可以通过几种方式处理:使用子查询、
不存在、
分组方式、
拥有子查询等。我将给出一个使用子查询的示例,但这可能不适合您,特别是如果所需标记的数量不总是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
)

tagid
如何既可以是
5
又可以是
8
?在(5,8)中执行
tagid也意味着
tagid!=10
。因此,您正在尝试查找所有同时具有
tagid
5和8的
photoid
s?一张照片可能有多个标记,我正在尝试查询所有具有特定标记的照片@火箭:在这个例子中,我想要所有的
photoid
s都有[italic]或者
tagid
1[italic]或者2,并且[italic]都有
tagid
5[italic]和8,而没有
tagid
10。@KevalPithva:
PhotoTags.tagid 10
有点多余吗?@RocketHazmat一张照片可能有四个标签,即,相同的
photoid
在表中出现四次,分别为
tagid
s2,5,8,10。在这种情况下,我不想在查询中找到匹配项,因为我不想看到任何带有
tagid
10的照片。
(PhotoTags.tagid)不在(10)
中是有效的SQL。您可以有一个值列表。建议的查询在
WHERE in
中有四个值,并且
count
匹配2,将匹配具有四个
tagid
中的两个或更多的
photoid
。这并不是我的目标。谢谢,但这和我最初的查询是一样的,对吗?是否可以将
和(tagid=1或tagid=2)
标准以某种方式添加到您的示例中?我已经更新了描述使它更清晰。不,它没有。您最初的查询实际上没有检查多个标记的同一photoid。如果您想添加
,那么只需将该子句添加到
HAVING
。这给了我一个错误:
靠近“ORDER”:语法错误
@AndersK:您可以尝试
GROUP\u CONCAT(tagid)
那么,这正是我想要实现的查询,很好的解释!(我必须检查这些解决方案是否对我有效)。谢谢,它似乎对示例有效。如果我需要在上面添加一个条件,比如:“至少有一个标记(15,16)”?您可以使用
DISTINCT
IN
连接到另一个子查询,例如:
内部连接(从PhotoTags中选择DISTINCT photoid,其中tagid IN(15,16))t5上的t5.photoid=t1.photoid
 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
)