在联接结果中过滤MySQL中的结果

时间:2020-02-16 09:00:19

标签: mysql sql

我是初学者程序员。我的MySQL查询有小问题。 这是我的MySQL数据:https://pastebin.com/69PcBSVH

我有这张桌子:

CREATE TABLE `dishes` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `company_id` bigint(20) UNSIGNED NOT NULL,
  `name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `description` longtext COLLATE utf8mb4_unicode_ci,
  `enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1',
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


CREATE TABLE `dish_values` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `dishes_id` bigint(20) UNSIGNED NOT NULL,
  `food_ingredient_id` bigint(20) UNSIGNED NOT NULL,
  `company_id` bigint(20) UNSIGNED NOT NULL,
  `quantity` decimal(9,2) NOT NULL DEFAULT '0.00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;


CREATE TABLE `food_ingredients` (
  `id` bigint(20) UNSIGNED NOT NULL,
  `company_id` bigint(20) UNSIGNED NOT NULL,
  `name` varchar(120) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `garbage` decimal(9,2) NOT NULL DEFAULT '0.00',
  `energy_value` decimal(9,2) NOT NULL DEFAULT '0.00',
  `protein` decimal(9,2) NOT NULL DEFAULT '0.00',
  `fat` decimal(9,2) NOT NULL DEFAULT '0.00',
  `available_carbohydrates` decimal(9,2) NOT NULL DEFAULT '0.00',
  `roughage` decimal(9,2) NOT NULL DEFAULT '0.00',
  `description` longtext COLLATE utf8mb4_unicode_ci,
  `url_address` varchar(160) COLLATE utf8mb4_unicode_ci NOT NULL,
  `allergen` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `allergen1` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `allergen2` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `allergen3` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `available_in_demo` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0',
  `enable` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

我的基地是准备菜肴所需的菜肴和食材的基地。

我需要显示所有不是过敏原的菜肴(food_ingredients.allergen = 0)。

Table dishes = given dishes
Table dish_values = ingredients that are assigned to a given dish
Food_ingredients table = ingredients of the dish.

过敏原的菜品在过敏原栏中的值为1,非过敏原的菜谱为0。

我查询以显示我的菜(没有过敏原):

SELECT 
  dishes.id, dishes.company_id, dishes.name, dishes.description, dishes.enable
FROM `dishes`  join dish_values on dish_values.dishes_id = dishes.id 
      join food_ingredients on food_ingredients.id = dish_values.food_ingredient_id 
WHERE food_ingredients.allergen = 0 
GROUP BY dishes.id

但是它不能正常工作。

结果,我既有含有过敏原的菜肴,也有不含过敏原的菜肴。

我该如何修理?

3 个答案:

答案 0 :(得分:0)

由于过敏原是char列,因此需要在0前后加上引号。或者,您可以将列更改为int。

答案 1 :(得分:0)

删除WHERE子句,并将条件添加到HAVING子句:

SELECT d.id, d.company_id, d.name, d.description, d.enable
FROM dishes d 
INNER JOIN dish_values v ON v.dishes_id = d.id 
INNER JOIN food_ingredients i ON i.id = v.food_ingredient_id 
GROUP BY d.id, d.company_id, d.name, d.description, d.enable
HAVING SUM(i.allergen) = 0 

条件SUM(i.allergen) = 0确保表food_ingredients中所有匹配的行都具有i.allergen = 0

答案 2 :(得分:0)

我将not’exists与相关子查询一起使用:避免了聚合的需求,这通常不利于大型数据集的性能:

select d.*
from dishes d
where not exists (
    select 1
    from dish_values v 
    inner join food_ingredients i on i.id = v.food_ingredient_id
    where 
        v.dishes_id = d.id 
        and i.allergen = 1
)

为了提高性能,您需要以下索引:food_ingredients(allergen, id)

旁注:由于allergen的数据类型仅包含0/1值,因此应将其从char(1)更改为tinyint(1)