Запрос SQL, чтобы получить продукты, связанные с флагами - PullRequest
2 голосов
/ 12 июля 2011

У меня есть таблица flags_products, как показано ниже (отношение «многие ко многим» между флагами и продуктами),

flags_products : 

flag_id --  product_id  
1      --   1   
2      --   1  
3      --   1  
1      --   2  
2      --   2  
4      --   2

Что такое SQL-запрос для получения строк, имеющих оба флага (flag_id's 1 и 2), связанных с продуктом (product_id)? Очевидно:

  SELECT * 
    FROM flags_products 
   WHERE flag_id = 1 
     AND flag_id = 2 
GROUP BY product_id;

... не работает и выдает пустой набор. Так какой будет правильный запрос?

Ответы [ 2 ]

4 голосов
/ 12 июля 2011

Точный подход, который вы должны предпринять, будет зависеть от ваших больших требований. Вот одно из возможных решений:

SELECT
    product_id
FROM
    Some_Table
WHERE
    flag_id IN (1, 2)
GROUP BY
    product_id
HAVING
    COUNT(*) = 2

Это работает, пока у вас не может быть дубликатов. Если товар может быть помечен дважды с одним и тем же flag_id, вам понадобится:

SELECT
    product_id
FROM
    Some_Table
WHERE
    flag_id IN (1, 2)
GROUP BY
    product_id
HAVING
    COUNT(DISTINCT flag_id) = 2

В обоих этих случаях вам потребуется GROUP BY, чтобы соответствовать вашему списку столбцов. MySQL не требует этого для выполнения запроса (недостаток IMO, но я сохраню этот аргумент в другой раз), но результаты не будут определены для столбцов, не входящих в GROUP BY. Вы также можете использовать вышеизложенное для запросов как подзапросов, которые затем можно присоединить к другой таблице или таблицам.

Если вы знаете, что всегда будет ровно два флага, для которых вы ищете, вы можете использовать EXISTS:

SELECT
    T1.product_id
FROM
    Some_Table T1
WHERE
    EXISTS (
            SELECT *
            FROM
                Some_Table T2
            WHERE
                T2.product_id = T1.product_id AND
                T2.flag_id = 1
           ) AND
    EXISTS (
            SELECT *
            FROM
                Some_Table T2
            WHERE
                T2.product_id = T1.product_id AND
                T2.flag_id = 2
            )

Хотя производительность может быть не очень хорошей.

0 голосов
/ 12 июля 2011

Вы можете использовать INTERSECT оператор.

SELECT product_id 
FROM t 
WHERE flag_id = 1

INTERSECT

SELECT product_id 
FROM t
WHERE flag_id = 2

Этот запрос вернет все product_id, которые имеют оба flag_id = 1 or 2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...