Delgus
@Delgus

Как правильно составить SQL-запрос?

Уважаемые знатоки SQL.
База данных:

product(продукты)
-id(int)
-name(varchar 255)

recipe(рецепты)
-id
-name(varchar 255)
-description(text)
-cooking_time(int) //время приготовления

recipe_product(связь рецепт-продукт)
-id(int)
-recipe_id(int)
-product_id(int)
-product_weight(int) //масса продукта

cooking_method(способ приготовления)
-id(int)
-name(int)

recipe_cooking_method(связь рецепт-способ приготовления)
-id(int)
-recipe_id(int)
-cooking_method_id(int)

Необходимо получить рецепты по id продуктов и их массе, по времени приготовления и по способу приготовления.
Вот как я пока делаю:

а) по id 1-го продукта (нестрогий поиск)
SELECT recipe.id,recipe.name,recipe.description,recipe.cooking_time
FROM recipe JOIN recipe_product
ON(recipe_product.recipe_id=recipe.id AND recipe_product.product_id = 1)


б) по id 1-го продукта и массе 1-го продукта (нестрогий поиск)
SELECT recipe.id,recipe.name,recipe.description,recipe.cooking_time
FROM recipe JOIN recipe_product
ON(recipe_product.recipe_id=recipe.id AND recipe_product.product_id = 1 AND recipe_product.product_weight > 800)


Но - это не строгий поиск, а как найти рецепты в которых есть только этот продукт, а других быть не должно. А как сделать такой поиск по нескольким продуктам и рецептам? Может БД неправильно спроектировал?
Подскажите плиз. Заранее благодарю)
  • Вопрос задан
  • 347 просмотров
Решения вопроса 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Если в таблице `recipe_product` пара (`recipe_id`, `product_id`) уникальная, то из данной таблицы можно удалить искусственный ключ `id` и сделать эту пару первичным ключом.
Поиск рецептов, в которые входят все указанные продукты:
SELECT `recipe_id`, COUNT(*) AS `count`
  FROM `recipe_product`
  WHERE (`product_id` = 1 AND `product_weight` > 100)
    OR (`product_id` = 2 AND `product_weight` BETWEEN 200 AND 400)
    OR (`product_id` = 3 AND `product_weight` < 10)
  GROUP BY `recipe_id`
  HAVING `count` = 3

Поиск рецептов, в которые входят все указанные продукты и ничего кроме них:
SELECT `recipe_id`, COUNT(*) AS `count`
  FROM `recipe_product`
  WHERE `recipe_id` NOT IN (SELECT `recipe_id` FROM `recipe_product` WHERE `product_id` NOT IN (1, 2, 3))
    AND ((`product_id` = 1 AND `product_weight` > 100)
      OR (`product_id` = 2 AND `product_weight` BETWEEN 200 AND 400)
      OR (`product_id` = 3 AND `product_weight` < 10))
  GROUP BY `recipe_id`
  HAVING `count` = 3
Ответ написан
@BorisKorobkov Куратор тега MySQL
Web developer
Необходимо получить рецепты по id продуктов и их массе, по времени приготовления и по способу приготовления.

join всех необходимых таблиц с условиями

как найти рецепты в которых есть только этот продукт, а других быть не должно? А как сделать такой поиск по нескольким продуктам и рецептам?

INNER JOIN recipe_product AS recipe_product1
ON ... 
AND recipe_product1.product_id = $productId1

INNER JOIN recipe_product AS recipe_product2
ON ... 
AND recipe_product2.product_id  = $productId2

LEFT JOIN recipe_product AS recipe_product_other
ON ... 
AND recipe_product_other.product_id NOT IN ($productId1, $productId2)
...
WHERE recipe_product_other.id IS NULL


P.S. Эффективность такого запроса оставляет желать лучшего. Запрос с group by из соседнего ответа гораздо эффективнее.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы