MySQL Query Question - PullRequest
       4

MySQL Query Question

0 голосов
/ 14 января 2011

Скажите, у меня есть следующие 3 таблицы:

users
id : int 11 primary autoinc
email : varchar 255

tags
id : int 11 primary autoinc
name : varchar 255

tag_union
id : int 11 primary autoinc
tag_id : int 11
target_id : int 11
target_type : enum( 'user','blog','other' )

Если мне дают список тегов, скажем, 1,3 и 8, я могу выбрать всех пользователей, у которых есть объединение ЛЮБОГО тегов, например:

SELECT *
FROM `users`
WHERE `id` IN( SELECT `target_id`
               FROM `tag_union`
               WHERE `tag_id` IN( '1','3','8')
                 && `target_type`=='user' )

Но как выбрать только пользователей, у которых есть объединение для ALL 3 тегов? Кажется, я не могу придумать, как это сделать одним запросом.

P.S. Извините за дерьмовый заголовок, кто-то может переименовать его, если придумает более подходящий.

Ответы [ 3 ]

2 голосов
/ 14 января 2011

Ваша производная таблица должна использовать GROUP BY / HAVING:

SELECT *
FROM users
WHERE id IN
(
    SELECT target_id
    FROM tag_union
    WHERE tag_id IN ('1', '3', '8') AND target_type = 'user'
    GROUP BY target_id
    HAVING COUNT(*) = 3
)

Обратите внимание, что в MySQL предложение IN может быть очень медленным. Лучше вместо этого использовать объединение.

SELECT *
FROM users T1
JOIN
(
    SELECT target_id
    FROM tag_union
    WHERE tag_id IN ('1', '3', '8') AND target_type = 'user'
    GROUP BY target_id
    HAVING COUNT(*) = 3
) T2
ON T1.id = T2.target_id

Я также предполагаю, что (target_type, tag_id) является уникальным в таблице tag_union.

0 голосов
/ 14 января 2011

Я обычно делаю это с группой, подходя к другому предложенному.Но для полноты картины это можно сделать и с помощью соединений.

select u.id
      ,u.other_columns
  from users u
  join tag_union t1 on(u.id = t1.target_id)
  join tag_union t2 on(u.id = t2.target_id)
  join tag_union t3 on(u.id = t3.target_id)
 where t1.target_type = 'user' and t1.tag_id = 1
   and t2.target_type = 'user' and t2.tag_id = 3
   and t3.target_type = 'user' and t3.tag_id = 8;
0 голосов
/ 14 января 2011
SELECT *
FROM `users`
WHERE `id` IN( SELECT `target_id`
               FROM `tag_union`
               WHERE `tag_id` IN ('1','3','8')
                 AND `target_type`='user' 
               GROUP BY `target_id`
               HAVING COUNT(DISTINCT `tag_id`) = 3)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...