从多对多表中选择

时间:2013-07-17 21:10:45

标签: php sql database select relational-division

我想获得post_ID和具有特定多个标签的帖子的缩略图。 我的表格如下:

table: post
-------------------
post_ID | thumbnail
1       | 1.jpg
2       | 2.jpg
3       | 3.jpg
4       | 4.jpg
5       | 5.jpg

table: tags
-----------
tag_ID | tag
1      | red
2      | yellow
3      | orange
4      | blue
5      | pink

table: post_tags
----------------
post_ID | tag_ID
1       | 1
1       | 2
1       | 4
1       | 5
2       | 2
2       | 3
3       | 4
3       | 1
3       | 2
4       | 5
4       | 4
5       | 1
5       | 3
5       | 5

我目前使用的是这样的东西,但它不起作用: 我首先获取数组中帖子的所有标签,然后比较它们以查找帖子是否包含所有3个标签。

 SELECT post_ID FROM post_tags 
 WHERE tag_ID IN ($thisTags[0], $thisTags[1], $thisTags[2], $thisTags[3])

我是否需要加入或组合或其他什么?我是SQL和PHP的新手。 非常感谢。

3 个答案:

答案 0 :(得分:0)

你在找这样的东西吗?

SELECT post_ID 
  FROM post_tags 
 WHERE tag_ID IN (1, 2) -- IN($thisTags[0], $thisTags[1], $thisTags[2], $thisTags[3])
 GROUP BY post_ID
 HAVING COUNT(DISTINCT tag_ID) = 2 -- COUNT(DISTINCT tag_ID) = 4

这是 SQLFiddle 演示

HAVING COUNT(DISTINCT tag_ID) = 2确保结果集仅包含post_ID值为{1}}的{​​{1}}

答案 1 :(得分:0)

如果你对post_tags(post_ID,tag_ID)有一个UNIQUE约束,并且你可以验证thisTags的元素是唯一的,那么你可以这样做:

SELECT post_ID FROM post_tags 
 WHERE tag_ID IN ($thisTags[0], $thisTags[1], $thisTags[2], $thisTags[3])
 GROUP BY post_ID
HAVING COUNT(1) = 4

这种方法要求$thisTags中的元素是唯一的。您可以轻松解决post_tags表中的唯一性问题(但上面的查询要求它也是唯一的。)

还有其他SQL语句,其他方法,可以实现相同的结果,但上面的查询是最简洁的。 (其他一些方法是使用EXISTS谓词,或对每个标记返回的post_ID集使用JOIN操作。)

答案 2 :(得分:0)

这是“set-within-sets”子查询的示例。我建议您使用group byhaving以获得最大的灵活性。我们的想法是将逻辑移到having子句中。在您的情况下,这看起来像:

SELECT post_ID
FROM post_tags 
group by post_id
having sum(tag_id = $thisTags[0]) > 0 and
       sum(tag_id = $thisTags[1]) > 0 and
       sum(tag_id = $thisTags[2]) > 0 and
       sum(tag_id = $thisTags[3]) > 0;

如果你只想 这些标签而没有其他标签:

SELECT post_ID
FROM post_tags 
group by post_id
having sum(tag_id = $thisTags[0]) > 0 and
       sum(tag_id = $thisTags[1]) > 0 and
       sum(tag_id = $thisTags[2]) > 0 and
       sum(tag_id = $thisTags[3]) > 0 and
       count(distinct tag_id) = 4;

如果你想要这四个标签中的至少三个:

SELECT post_ID
FROM post_tags 
group by post_id
having (max(tag_id = $thisTags[0]) + and
        max(tag_id = $thisTags[1]) + and
        max(tag_id = $thisTags[2]) + and
        max(tag_id = $thisTags[3])
       ) >= 3;