我可能会遗漏一些明显的东西,但我需要一个只返回同一列上符合多个条件的记录的查询。
该表是一个简单的链接表,可以将标签链接到照片,即标签可以应用于多张照片,而照片可以有多个标签。
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 IN
和GROUP 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)
条件?
答案 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)
好像你想要找到所有照片:
第一个要求可以使用IN
子句和SELECT DISTINCT
轻松处理。
第二个要求可能最好使用NOT EXISTS
处理。
可以通过多种方式处理第三项要求:使用子查询,NOT EXISTS
,GROUP 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
)