SQL: отношение «многие ко многим» и предложение «ALL» - PullRequest
0 голосов
/ 26 сентября 2018

У меня есть таблица products и таблица locations, которые связаны во взаимосвязи «многие ко многим» с таблицей products_locations.Теперь клиент может выбрать набор продуктов, и я хочу выполнить запрос, который выбирает только места, в которых доступны ВСЕ выбранные продукты.

Сначала это казалось довольно простым, но я вижу себябудучи совершенно сбит с толку тем, как этого добиться.Сначала я думал, что смогу получить все правильные идентификаторы местоположения с помощью чего-то вроде

SELECT location_id
FROM products_locations
WHERE product_id = ALL [the user selected product ids]

Но, если подумать, это тоже не имеет смысла (структура products_locations довольно проста [product_id, location_id].

Буду признателен за любые предложения о том, как структурировать такой запрос. Мне кажется, что я пропускаю что-то простое ..

РЕДАКТИРОВАТЬ: я использую mysql синтаксис / диалект

Быстрый пример: с учетом следующих таблиц

| products   | | locations | | products_locations       |
| id | name  | | id | name | | product_id | location_id |
|------------| |-----------| |--------------------------|
| 1  | prod1 | | 1  | locA | | 1          | 2           |
| 2  | prod2 | | 2  | locB | | 2          | 1           |
| 3  | prod3 | |-----------| | 2          | 2           |
|------------|               | 3          | 1           |
                             |--------------------------|

Если пользователь выбирает продукты 1 и 2, запрос должен возвращать только местоположение 2. Если пользователь выбирает продукты 2 и 3, запрос должен возвращать местоположение 1Для 1, 2 и 3 местоположение не будет действительным, а для продукта 2 оба местоположения будут действительными.

1 Ответ

0 голосов
/ 27 сентября 2018

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

SELECT t.location_id
FROM (SELECT location_id, COUNT(*) as n_hits
      FROM products_locations
      WHERE product_id IN [the user selected products]
      GROUP BY location_id) t
WHERE n_hits = [the number of user selected products];

Объяснение:

  1. Я создаю временную таблицу t, которая содержит каждый location_id, в котором есть по крайней мере один соответствующий продукт в выборе пользователя, а также количество раз, когда это местоположение соответствует продукту в выборе пользователя.Это достигается путем группировки запроса по location_id.
  2. . Я выбираю location_id (s) из этой временной таблицы t, где число совпадений равно количеству продуктов, которые имел пользовательвыбран.Если это число меньше, я знаю, что хотя бы один продукт не соответствует этому местоположению.
...