2010-07-30 3 views
1

У меня есть четыре таблицы:поиск в совместных таблицах

cuisines(id, name); 

recipes(id, cuisine_id, name, picture); 

ingredients(id, name); 

ingredients_recipes(ingredient_id, recipe_id); 

последняя таблица ссылающихся многие-ко-многим отношения между рецепты и ингредиенты. Как я могу выбрать все кухни, которые содержат томаты (то есть в кухне есть рецепты, которые содержат ингредиенты, которые называются «томаты»)?

Я использую это в SQLite, но я думаю, что это то же самое на всех языках SQL?

ответ

0

Присоединяйтесь к ним все в соответствии с внешними ключами, фильтр на ingredient_name = «Tomatoe», группы по всем столбцам таблица кухни вы заинтересованы в

SELECT cuisine.id, cuisine.name 
    FROM cuisine 
    INNER JOIN recipe on recipe.cuisine_id = cuisine.id 
    INNER JOIN ingredients_recipes ir ON ir.recipe_id = recipe.id 
    INNER JOIN ingredients on ingredients.id = ir.ingredient_id 
    WHERE ingredients.name = 'Tomatoe' 
    GROUP BY cuisine.id, cuisine.name 
3

Вы можете попробовать INNER JOIN ИНГ все четыре таблицы, как показано в следующем примере:

SELECT  DISTINCT c.name 
FROM  cuisines AS c 
INNER JOIN recipes AS r ON (r.cuisine_id = c.id) 
INNER JOIN ingredients_recipes AS ir ON (ir.recipe_id = r.id) 
INNER JOIN ingredients AS i ON (i.id = ir.ingredient_id) 
WHERE  i.name = 'tomatoes'; 
+0

это не даст вам повторять имена кухни для кухни, которые имеют несколько рецептов с помидорами? Требуется ли 'SELECT DISTINCT c.name'? – markusk

+0

@markusk: Да, хорошая точка. Или 'DISTINCT', либо' GROUP BY'. Обновлен мой ответ. –

0

подзапросов вариант:.

SELECT name 
FROM cuisines 
WHERE id IN (
    SELECT cuisine_id 
    FROM recipes r 
    JOIN ingredients_recipes ir ON r.id = ir.recipe_id 
    JOIN ingredients i ON ir.ingredient_id = i.id 
    WHERE i.name = 'Tomatoes' 
) 
0

Я бы предложил использовать подзапросы вместо соединений. Что-то вроде ...

SELECT * 
    FROM cuisine 
    WHERE cuisine_id IN (
      SELECT cuisine_id 
       FROM recipe 
       WHERE recipe_id IN (
         SELECT recipe_id 
          FROM recipe_ingredients 
          WHERE ingredient_id IN (
             SELECT id 
             FROM ingredients 
             WHERE TOUPPER(name) LIKE '%TOMATO%'))); 

В любом случае, я думаю, вы должны быть осторожны с совпадением слова; больше, чем другие корреспонденты, так как вы не хотите пропустить такие ингредиенты, как «Четыре небольших помидора» или «Один большой томат» или «Томатное пюре».

+0

привет, спасибо за это. В чем преимущество подзапросов над объединениями? – ChrisB

+0

Я считаю, что подзапросы легче понять, чем объединяться, и меньше подвержены ошибкам, хотя я подозреваю, что я в меньшинстве в этом отношении. По общему признанию, расширенное гнездо, подобное приведенному выше, не является особенно привлекательным примером. Вы делаете то, что вам больше нравится. Часто говорят, что подзапросы медленнее, чем объединения; Я так и не нашел этого. Оптимизатор запросов вполне способен переписывать подзапрос как соединение, если он считает нужным. –

+0

Подзапросы медленны, как вы признались. Поэтому нет причин научиться использовать thoses, если у вас есть более быстрые варианты. – newbie

0

EXISTS вариант:

SELECT name 
FROM cuisines c 
WHERE EXISTS 
( SELECT NULL 
    FROM recipes r 
    JOIN ingredients_recipes ir ON r.id = ir.recipe_id 
    JOIN ingredients i ON ir.ingredient_id = i.id and i.name = 'tomatoes' 
    WHERE r.cuisine_id = c.id 
) 
Смежные вопросы