Извлечение только тех строк, которые соответствуют всем записям в объединенной таблице (SQL) - PullRequest
2 голосов
/ 02 декабря 2008

У меня есть следующие пять таблиц:

  • ISP
  • Продукт
  • Подключение
  • аддон
  • AddOn / Product (сводная таблица для отношения многие ко многим).

Каждый Продукт связан с Интернет-провайдером, каждое Соединение перечислено с Продуктом. Каждый продукт может иметь несколько надстроек, используя сводную таблицу (которая просто имеет 2 поля, одно для идентификатора продукта и одно для идентификатора AddOn).

Результат, который меня интересует, - это каждое соединение с перечисленными аддонами (для этого я использую GROUP_CONCAT MySQL, чтобы создать разделенный запятыми список поля name дополнения). Это работает отлично, как есть, запрос выглядит примерно так:

SELECT i.name AS ispname, i.img_link, c.download, c.upload, c.monthly_price, c.link, 
GROUP_CONCAT(a.name) AS addons, SUM(pa.monthly_fee) AS addon_price
FROM isp i JOIN product p ON i.id = p.isp_id
JOIN `connection` c ON p.id = c.product_id LEFT JOIN product_addon pa ON pa.product_id = p.id AND pa.forced = 0
LEFT JOIN addon a ON pa.addon_id = a.id GROUP BY c.id

Я использую ЛЕВЫЕ СОЕДИНЕНИЯ, поскольку продукты могут вообще не иметь надстроек.

Моя проблема в том, что можно выбрать некоторые дополнения, которые ДОЛЖНЫ иметь перечисленные соединения, представленные в виде списка идентификаторов дополнений, например (1,14,237). Если я добавлю его в качестве дополнительного условия в операторах JOIN ( AND pa.addon_id IN (...) ), он вернет все соединения, которые имеют только один из перечисленных аддонов, но не обязательно все из них.

Есть ли какой-нибудь способ вернуть все соединения, которые как минимум имеют все дополнения (они могут иметь и дополнительные) через SQL?

Ответы [ 2 ]

2 голосов
/ 02 декабря 2008
GROUP BY set-of-column
HAVING SUM(CASE WHEN ISNULL(pa.addon_id, 0) IN (1,14,237) THEN 1 ELSE 0 END) = 3
0 голосов
/ 02 декабря 2008

Вы можете добавить к предложению WHERE:

AND NOT EXISTS (SELECT NULL FROM addon a2
                WHERE  a2.addon_id IN (1,14,237)
                AND NOT EXISTS
                ( SELECT NULL
                  FROM   product_addon pa2
                  WHERE  pa2.addon_id = a2.addon_id
                  AND    pa2.product_id = p.product_id
                )
               )

Или эквивалентно:

AND NOT EXISTS (SELECT NULL FROM addon a2
                LEFT JOIN product_addon pa2
                  ON pa2.addon_id = a2.addon_id
                 AND pa2.product_id = p.product_id
                WHERE a2.addon_id IN (1,14,237)
                AND   pa2.product_id IS NULL
                )
               )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...