【问题标题】:SQL - using result from subquerySQL - 使用子查询的结果
【发布时间】:2012-11-22 18:32:49
【问题描述】:

我的 SQLLite 数据库中有两个表。我正在尝试取回可以使用输入的成分制作的饮料。

我正在尝试制定此查询以获得我想要的。

餐桌饮品

drink_id |标题 |成分|方向 |成分编号

示例行看起来像

1 |蓝爸爸 | 1 根碎蓝冰棒、8 盎司酷爱饮料、4 盎司伏特加 |方向 | 3

餐桌食材

drink_id |成分

示例行看起来像

1 |蓝色冰棒

我现在的查询

这是我想要返回的部分伪代码(在我得到这个之后,我会动态地输入要查询的术语)。

我想返回所有输入量等于或大于饮料成分编号的饮料,并且那些输入的成分与饮料中所需的所有成分匹配。

SELECT drinks.title, drinks.ingredients, drinks.directions
FROM drinks, (SELECT count(ingredients._id) as ingredientNumber FROM ingredients
WHERE ingredients.ingredient LIKE '%rum%'
GROUP BY ingredients._id) as foundIngredients
WHERE drinks.ingredientsNum = foundIngredients.ingredientNumber;

谁能帮助我获得最适合的查询,甚至给我一些关于重组我的数据库模型的提示?我刚刚从一个 80k 行的长 JSON 文件创建了这个数据库。

【问题讨论】:

  • 这是您的实际架构吗?您通过将成分数据包含在两个地方来对成分数据进行非规范化?表之间的关系是什么?似乎您需要一个包含外键drink_id 和component_id 的连接表。你能澄清一下吗?
  • 是的,这是实际的架构。我的意思是我可以改变它,但最适合最好的查询。我正在尝试在 android 手机上查询它并希望它非常快。我认为将程序 (|) 中已经被实际分隔符分割的所有成分放入成分表中可能会更快。

标签: android sql json sqlite


【解决方案1】:

反映已澄清问题的查询:

SELECT drinks.title, drinks.ingredients, drinks.directions
FROM drinks
WHERE drinks.ingredientsNum = (
    SELECT count(*)
    FROM ingredients
    WHERE (
        ingredients.ingredient LIKE '%rum%'
        OR ingredients.ingredient LIKE '%coke%'
        OR ingredients.ingredient LIKE '%vodka%'
        -- the same goes for each ingredient
    )
    AND ingredients.drink_id = drinks.drink_id
)

同样,如果您允许饮料含有额外的成分除了所有指定的

SELECT drinks.title, drinks.ingredients, drinks.directions
FROM drinks
WHERE drinks.ingredientsNum >= [number of input ingredients]
AND [number of input ingredients] <= (
    SELECT count(*)
    FROM ingredients
    WHERE (
        ingredients.ingredient LIKE '%rum%'
        OR ingredients.ingredient LIKE '%coke%'
        OR ingredients.ingredient LIKE '%vodka%'
        -- the same goes for each ingredient
    )
    AND ingredients.drink_id = drinks.drink_id
)

【讨论】:

  • 我想返回所有满足给定输入的饮料。例如:Drink needs rum and vodka to make and the input is rum and vodka.Drink has rum, coke, and vodka to make and the input is rum, coke, and vodka.
  • 我稍微编辑了我想要的内容。如果输入了 3 种成分,我想退回包含 3 种成分的饮料,并且这些成分都与输入的成分匹配。
  • 不,人们不能去商店购买他们没有的东西。所以输入的成分必须等于或大于饮料的成分编号,并且成分必须匹配。
  • 好吧,我想你在这里找到了正确的答案。我真的很亲近。我稍后会尝试一下,然后告诉你它是怎么回事。如果您可以投票支持我的问题,我可以投票支持您的问题(我需要 15 个代表)。
  • 嗯,DB 规范化并不是关于好看的模式的笑话。如果做得好,它可以生成更好的 DBMS 使用的查询计划来确定如何实际执行任何查询,包括 SELECT。此外,它还允许应用程序具有更少(理想情况下没有)数据冗余,这意味着要处理的数据更少,从而可以更快地执行。但根据我的经验,对于移动设备来说,这可能有点过头了。
【解决方案2】:

您的架构有点奇怪,因为通常您实际上可能会使用 3 个表来真正规范化这个数据结构(饮料、配料、drink_ingredients 或类似的)。但是,由于您正在进行文本搜索,并且您已经在饮料表中获得了所有成分名称,因此您可以简单地在饮料表中查询:

SELECT title, ingredients, directions
FROM drinks
WHERE ingredients LIKE '%rum%'
AND ingredients LIKE '%vodka%'
... // add more ingredients as needed 

确保您在成分字段上有一个索引。请注意,如果您想退回所有带有朗姆酒和/或伏特加酒的饮料,您可以将 AND 更改为 OR

【讨论】:

  • 现在我将如何编写 SQL 语句来确保饮料中的所有成分都得到满足?
  • 那么你可能需要考虑规范化你的数据,因为文本搜索不会得到你想要的。您可能需要对成分进行文本搜索以确定成分 ID,然后使用和 Drinks_to_ingredients 多对多连接表进行搜索。为了使用高效的查询,您可能还需要将任务分解为多个查询。
  • 当我只想做 SELECT 时,为什么还要规范化这个数据库?我没有做任何形式的改变。
猜你喜欢
  • 2015-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 2017-05-29
  • 2015-02-07
  • 2015-02-27
  • 1970-01-01
相关资源
最近更新 更多