如何获得配方配料表中每个配方id的唯一配料数mysql数据库

6ovsh4lw  于 2021-06-25  发布在  Mysql
关注(0)|答案(3)|浏览(242)

我正在运行一个查询,查找含有特定成分的配方。这些配料与查询一起发送,例如“糖、牛奶、鸡蛋”。然后根据在其中找到的配料量对配方(配方id)进行排序,因此如果配方中包含糖、牛奶和鸡蛋,则会在只包含两种配料的配方之前进行排序。
查询

SELECT
    recipe_id, COUNT(ingredient) AS ingredient_count
FROM
    ingredients
WHERE
    ingredient LIKE '%sugar%'
    OR ingredient LIKE '%milk%'
    OR ingredient LIKE '%egg%'
GROUP BY
    recipe_id
ORDER BY
    ingredient_count DESC;

配料表

id | recipe_id | ingredient      |
---|-----------|-----------------|
1  | 1         | 2 cups of sugar |

...

由于所有的数据都被忽略了,配料表的结构不好。配料按单位和数量混合,例如“2杯糖”。这就是为什么我必须使用通配符来查找配料。一个食谱也可以有一种成分多次,例如“1杯糖”和“2杯糖”(这是由于子食谱),这是我开始出现问题的地方。因为我的where子句会在一个配方中找到2个“糖”,配料的数量会增加2(ofc),但我只希望它增加1,因为只有一个配料“糖”。
所以我要做的是以某种方式计算查询返回的所有成分,但是如果一种成分被多次找到,例如“2杯糖”,“1杯糖”,我只想将其计算为1,因为它们都有“糖”。
这个查询执行我想要的计数操作,但是由于某些原因,它只返回很少的配方,而应该返回更多的配方。
这个问题不是我提出的

SELECT result.recipe_id, COUNT(*) FROM ( 
    SELECT
        recipe_id, ingredient
    FROM
        ingredients
    WHERE
        (ingredient LIKE '%sugar%')
        OR (ingredient LIKE '%milk%')
        OR (ingredient LIKE '%egg%')
    GROUP BY
        CASE
            WHEN ingredient LIKE '%sugar%' THEN 'sugar'
            WHEN ingredient LIKE '%milk%' THEN 'milk'
            WHEN ingredient LIKE '%egg%' THEN 'egg'
            ELSE NULL
        END
    ) AS result
GROUP BY result.recipe_id;
0kjbasz6

0kjbasz61#

@ast tm答案扩展:
这个答案仍然没有解决“成分多次”的重复计算问题。另外,最初的问题需要按配方分组的结果。
然而,我仍然不确定它是否在技术上给了你“独特成分的数量”,只有糖、牛奶或鸡蛋成分的数量。e、 如果一份食谱中有10种其他成分(不是牛奶、糖或鸡蛋),那么这些成分在计算时将被忽略。
在查询中输入所有可能的成分名称的想法通常都是糟糕的设计。查询很快就会变得混乱。但如果有帮助的话:

SELECT *, 
       IF(ingredient LIKE '%sugar%', 1, 0) as sgr,
       IF(ingredient LIKE '%milk%', 1, 0) as mlk,
       IF(ingredient LIKE '%egg%', 1, 0) as gg
FROM
    ingredients
    WHERE
        (ingredient LIKE '%sugar%')
        OR (ingredient LIKE '%milk%')
        OR (ingredient LIKE '%egg%')
GROUP BY
    recipe_id
ORDER BY
    (MAX(sgr) + AMX(mlk) + MAX(gg)) DESC;

如果你还想考虑其他成分,可以尝试将where移到having子句,并使用group\u concat(但除了“糖”、“牛奶”或“鸡蛋”外,仍然不能解决重复计算问题)。
这可能有助于更接近您的需求:

SELECT *, 
       IF((ingredient NOT LIKE '%sugar%' AND ingredient NOT LIKE '%milk%' AND ingredient NOT LIKE '%egg%'), 1, 0) as others,
       IF(ingredient LIKE '%sugar%', 1, 0) as sgr,
       IF(ingredient LIKE '%milk%', 1, 0) as mlk,
       IF(ingredient LIKE '%egg%', 1, 0) as gg
FROM
    ingredients
GROUP BY
    recipe_id
HAVING
        (GROUP_CONCAT(ingredient) LIKE '%sugar%')
        OR (GROUP_CONCAT(ingredient) LIKE '%milk%')
        OR (GROUP_CONCAT(ingredient) LIKE '%egg%')
ORDER BY
    (others + MAX(sgr) + AMX(mlk) + MAX(gg)) DESC;
qni6mghb

qni6mghb2#

SELECT *, 
       IF(ingredient LIKE '%sugar%', 1, 0) as sgr,
       IF(ingredient LIKE '%milk%', 1, 0) as mlk,
       IF(ingredient LIKE '%egg%', 1, 0) as gg
FROM
    ingredients
    WHERE
        (ingredient LIKE '%sugar%')
        OR (ingredient LIKE '%milk%')
        OR (ingredient LIKE '%egg%')
ORDER BY sgr + mlk + gg DESC;
h6my8fg2

h6my8fg23#

如果您可以将“unit”和“component\u name”分为两个单独的列,那么您可以通过以下方式完成:

SELECT
    recipe_id, COUNT(DISTINCT ingredient_name) AS ingredient_count
FROM
    ingredients
WHERE
    ingredient_name LIKE '%sugar%'
    OR ingredient_name LIKE '%milk%'
    OR ingredient_name LIKE '%egg%'
GROUP BY
    recipe_id
ORDER BY
    ingredient_count DESC;

但是您要问的是,对于mysql来说,对于像“1 cup of sugar”这样的字符串,“1 cup”和“sugar”是它可以操作的两个独立值。
然而,如果你总是可以指望“of”是一个分隔符,你可以尝试使用一些mysql字符串搜索和切分函数的巧妙使用来计算成分名称。由于性能非常差,这会将上述查询中的“配料名称”替换为:

SUBSTR(ingredient,LOCATE(' of ', ingredient)+4)

相关问题