Сложный SQL Query Строка Внутреннее Объединение Общий Знаменатель - PullRequest
3 голосов
/ 31 августа 2009

Это очень очень важный SQL-запрос, после которого базируется весь мой сайт ..

и он не работает ..

Трудно объяснить без примера ..

Есть 2 таблицы, одна - «Таблица ингредиентов», а другая - «Таблица продуктов».

В IngredentsTable У меня есть следующее

  1. Хлеб
  2. ChickenBreast
  3. Лапша
  4. 1020 * майонез *
  5. Сыр
  6. Кетчуп
  7. масло

и ProductsTable

  1. Spageti
  2. Сэндвич с куриной грудкой

И есть ТАБЛИЦА MAPPING, которая соединяет обе таблицы. Имеет IngredientID и ProductID

Теперь Таблица сопоставления Сэндвич с куриной грудкой - хлеб

Сэндвич с куриной грудкой - майонез

Сэндвич с куриной грудкой - сыр

Сэндвич с куриной грудкой - кетчуп

Спагети --- Лапша

Спагети --- Сыр

Спагети --- Кетчуп

Вы заметите, что Cheese и Ketchup являются общими записями как для куриной грудки, так и для Spageti

Я хочу написать SQL-запрос, который получает идентификаторы продуктов, которые имеют указанные ингредиенты.

Я могу добиться этого частично с помощью следующего запроса

SELECT 
  ProductTable.id,
  ProductTable.Name 
FROM ProductTable 
INNER JOIN MappingTable 
  ON ProductTable.id = MappingTable.ProductID
WHERE MappingTable.IngredientID =  5; 

Предположим, что 5 был сыром, я успешно смог получить результаты сэндвича с куриной грудкой и спагети

Но если я добавлю еще один, WHERE MappingTable.IngredientID = 5,6; 6, являющийся хлебом, он должен показывать только бутерброд с куриной грудкой, а НЕ спагетти

Я получаю сообщение об ошибке "," синтаксис .. даже "и" не получает результатов.

Как проверить несколько ингредиентов, например WHERE MappingTable.IngredientID = 5,6,7;

ЛЮБАЯ ПОМОЩЬ ОЧЕНЬ ЦЕНА !!!

мне нужно иметь это в одном запросе ..

Пожалуйста, покажите мне варианты

Ответы [ 5 ]

3 голосов
/ 31 августа 2009

С 2 запросами вы можете использовать пересечение ваших результатов

Но вы говорите, что хотите в одном запросе.

Близким приближением будет иметь группирование по утверждению и подсчет количества строк, полученных из вашего результата. Он должен быть равен количеству ваших ингредиентов. Это не сработает, если ваши ингредиенты повторяются более одного раза в одном и том же продукте.

что-то вроде этой строки для 2 идентификаторов ингредиентов:

SELECT ProductTable.id, ProductTable.Name FROM ProductTable 
INNER JOIN MappingTable ON ProductTable.id = MappingTable.ProductID 
WHERE MappingTable.IngredientID in (5,6) group by ProductTable.id, ProductTable.Name 
HAVING count(*) = 2;
1 голос
/ 31 августа 2009

Прежде всего, отредактируйте ваш вопрос так, чтобы данные в ваших таблицах примеров соответствовали примеру вопроса ... Если 5 - сыр, а 6 - хлеб, то сделайте так, чтобы таблица ингредиентов соответствовала этому. иначе это сбивает с толку.

Во-вторых, вы утверждаете, что «он должен показывать только бутерброд с куриной грудкой, а НЕ спагет» заставляет меня думать, что вы хотите знать продукты, которые имеют ВСЕ перечисленные ингредиенты, а не ЛЮБОЙ из них. Если это так, то вы хотите следующее

  Select P.id,  P.Name 
  FROM ProductTable P 
  Where Exists (Select * From Mapping Table
                Where ProductId = P.ProductId
                    And IngredientId = 5)
    And Exists (Select * From Mapping Table
                Where ProductId = P.ProductId
                    And IngredientId = 6)
    And Exists (Select * From Mapping Table
                Where ProductId = P.ProductId
                    And IngredientId = 7)

или логика подсчета us8ng:

   Select P.id,  P.Name 
   From ProductTable P 
   Where (Select Count(Distinct IngredientId)
          From MappingTable M
          Where ProductId = P.ProductId 
            And IngredientId In (5,6,7)) = 3
1 голос
/ 31 августа 2009
WHERE MappingTable.IngredientID IN (5, 6, 7)

Извините, мой плохой. Как насчет этого?

SELECT 
  p.id,
  p.Name 
FROM ProductTable p
INNER JOIN (SELECT * FROM MappingTable WHERE IngredientID IN (5, 6, 7)) m
  ON p.id = m.ProductID
0 голосов
/ 31 августа 2009

Это должно сработать, хотя вам нужно указать для него две «переменные»: первая - это набор IngredientID, разделенных запятыми, а вторая (@IngredientsCount) - количество ингредиентов в этом списке.

SELECT ProductsTable.id, ProductTable.Name
FROM ProductsTable
INNER JOIN (SELECT ProductID, Count(*) AS Ingredients
    FROM MappingTable
    WHERE IngredientID IN (...ids of ingredients here...)
    GROUP BY ProductID
    HAVING Count(*) = @IngredientsCount) AS ProductIngredients ON ProductsTable.ProductID = ProductIngredients.ProductID

Если возможно, чтобы один и тот же ингредиент был записан дважды (хотя структура вашей таблицы не выглядит так, как это допускается, и, вероятно, в этом нет необходимости), переключите два Count (*) на Count (Distinct IngredientID) и измените @IngredientCount - количество используемых ингредиентов.

0 голосов
/ 31 августа 2009

Вам необходимо привязать таблицу соответствия отдельно для каждого ингредиента:

SELECT 
  ProductTable.id,
  ProductTable.Name 
FROM ProductTable 
INNER JOIN MappingTable AS MappingTable1
  ON ProductTable.id = MappingTable1.ProductID
  AND MappingTable1.IngredientID = 5
INNER JOIN MappingTable AS MappingTable2
  ON ProductTable.id = MappingTable2.ProductID
  AND MappingTable2.IngredientID = 6

Если вы используете оператор IN, как предлагали другие авторы, вы получите и спагетти, и сэндвич с курицей для хлеба и сыра, потому что IN по сути является запросом типа OR.

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