并在MySQL上搜索多对多表

时间:2013-01-09 14:55:28

标签: mysql sql select many-to-many

我想在下面的表格中搜索:

Table A
+----+----------------------------+
| ID | description                |
+----+----------------------------+
|  0 | horse going bad            |
|  1 | Older Years of Resolutions |
|  2 | The knockknock pirate      |
|  3 | The Wish list              |
|  4 | list that's no list        |
+----+----------------------------+

table TAGS
+----+------------+
| ID | tag        |
+----+------------+
|  0 | list       |
|  1 | knockknock |
+----+------------+

table TAGLINKS
+-------+--------+
| TAGID | JOKEID |
+-------+--------+
|   0   |    2   |
|   0   |    3   |
+-------+--------+

当我进行搜索时:

select A.* from tags
   join taglinks on tagid=tags.id
   join A on A.id=jokeid
where tag in ('list','knockknock') 

给我A中的所有条目,其标签中有“EITHER'列表'或'knockknock'(或两者)(2,3)。我正在寻找的是从表A获取连接到BOTH列表和knockknock标记的条目的查询(仅限2)。

我也是在表A的描述中直接搜索这些数据,这是值得考虑的事情。

现在我有:

select A.* from tags
   join taglinks on tagid=tags.id
   join A on A.id=jokeid
where tag in ('list','knockknock') 

UNION

select * from A where locate('list',description) and locate('knockknock',description)

但我从表A得到3,我只想要2

2 个答案:

答案 0 :(得分:2)

要确保所有标记都'list', 'knockknock',您应该在GROUP BY添加HAVING子句:

...
WHERE tag in ('list', 'knockknock')
GROUP BY tag
HAVING COUNT(tag) = 2)

类似的东西:

SELECT A.* 
FROM tags
INNER JOIN taglinks ON tagid = tags.id
INNER JOIN A on A.id=jokeid
WHERE id IN (SELECT id
             FROM tags
             WHERE tag in ('list', 'knockknock')
             GROUP BY tag
             HAVING COUNT(tag) = 2)

答案 1 :(得分:1)

这是将标签视为一组并查找该组属性的示例。我喜欢使用SQL的聚合函数来处理它,特别是having子句。

select A.*
from tags join
     taglinks
     on tagid=tags.id join
     A on A.id=jokeid
group by A.id
having max(tag = 'list') = 1 and
       max(tag = 'knockknock') = 1

(注意:这使用两种特定于MySQL的语法约定。group by仅在id列上;其余为“隐藏列”。而且,表达式tag = 'list'被视为真实value,因此不需要完整的case语句。)

顺便说一句,将其切换到一个或另一个标签很容易:

select A.*
from tags join
     taglinks
     on tagid=tags.id join
     A on A.id=jokeid
group by A.id
having max(tag = 'list') = 1 or
       max(tag = 'knockknock') = 1