1

我正在努力解决如何对此进行查询。我有三张桌子……配料、食谱和商店。我正在尝试构建一个查询,该查询将告诉我可以从商店的可用原料中制作哪些食谱。我的桌子是:

    mysql> SELECT * FROM 成分;
    +----------+
    | 编号 |
    +----------+
    | 苹果| 高分辨率照片| CLIPARTO
    | 牛肉|
    | 奶酪 |
    | 鸡|
    | 鸡蛋| 高分辨率照片| CLIPARTO
    | 面粉|
    | 牛奶|
    | 意大利面|
    | 糖|
    | 番茄| 高分辨率照片| CLIPARTO
    +----------+
    10 行一组(0.00 秒)

    mysql> 选择 * FROM 商店;
    +------------+------------+
    | 姓名 | 成分|
    +------------+------------+
    | 目标 | 苹果| 高分辨率照片| CLIPARTO
    | 目标 | 鸡|
    | 目标 | 面粉|
    | 目标 | 牛奶|
    | 目标 | 糖|
    | 沃尔玛| 牛肉|
    | 沃尔玛| 奶酪 |
    | 沃尔玛| 面粉|
    | 沃尔玛| 牛奶|
    | 沃尔玛| 意大利面|
    | 沃尔玛| 番茄| 高分辨率照片| CLIPARTO
    +------------+------------+
    11 行(0.00 秒)

    mysql> 选择 * 从食谱;
    +---------------+------------+
    | 姓名 | 成分|
    +---------------+------------+
    | 苹果派| 高分辨率照片| CLIPARTO 苹果| 高分辨率照片| CLIPARTO
    | 苹果派| 高分辨率照片| CLIPARTO 面粉|
    | 苹果派| 高分辨率照片| CLIPARTO 牛奶|
    | 苹果派| 高分辨率照片| CLIPARTO 糖|
    | 芝士汉堡| 牛肉|
    | 芝士汉堡| 奶酪 |
    | 芝士汉堡| 面粉|
    | 芝士汉堡| 牛奶|
    | 炸鸡| 鸡|
    | 炸鸡| 面粉|
    | 意大利面| 牛肉|
    | 意大利面| 意大利面|
    | 意大利面| 番茄| 高分辨率照片| CLIPARTO
    +---------------+------------+
    13 行一组(0.00 秒)

    mysql>

鉴于上述情况,我想构建一个查询,在其中我给它提供商店名称(例如沃尔玛),它会生成我可以从沃尔玛(芝士汉堡和意大利面)的可用原料中制作的食谱列表。

下面是创建这些表的 SQL:

    如果成分不存在则创建表(
      id varchar(32) 非空,
      主键(id)
    ) 引擎=InnoDB 默认字符集=latin1;

    插入成分 (id) 值
    ('苹果'),
    ('牛肉'),
    ('起司'),
    ('鸡'),
    ('蛋'),
    ('面粉'),
    ('牛奶'),
    ('意大利面'),
    ('糖'),
    ('番茄');

    CREATE TABLE IF NOT EXISTS recipes (
      `name` varchar(32) NOT NULL,
      成分 varchar(32) NOT NULL,
      主键(`名称`,成分)
    ) 引擎=InnoDB 默认字符集=latin1;

    插入食谱(`名称`,成分)值
    ('苹果派', '苹果'),
    ('苹果派', '面粉'),
    ('苹果派','牛奶'),
    ('苹果派', '糖'),
    ('芝士汉堡','牛肉'),
    ('芝士汉堡','奶酪'),
    ('芝士汉堡','面粉'),
    ('芝士汉堡','牛奶'),
    ('炸鸡', '鸡'),
    ('炸鸡','面粉'),
    (“意大利面”,“牛肉”),
    (“意大利面”,“意大利面”),
    (“意大利面”,“番茄”);

    CREATE TABLE IF NOT EXISTS 商店 (
      `name` varchar(32) NOT NULL,
      成分 varchar(32) NOT NULL,
      唯一键名称_INGREDIENT(`名称`,成分)
    ) 引擎=InnoDB 默认字符集=latin1;

    插入商店(`名称`,成分)值
    ('目标', '苹果'),
    ('目标', '鸡'),
    ('目标', '面粉'),
    ('目标','牛奶'),
    ('目标', '糖'),
    ('沃尔玛','牛肉'),
    ('沃尔玛','奶酪'),
    ('沃尔玛','面粉'),
    ('沃尔玛','牛奶'),
    ('沃尔玛','意大利面'),
    (“沃尔玛”,“番茄”);

4

4 回答 4

3

尝试这个:

SELECT r.name FROM recipes r          
GROUP BY r.name
HAVING COUNT(*) = (SELECT COUNT(*) 
     FROM recipes r2 INNER JOIN stores s 
        ON r2.ingredient = s.ingredient AND s.name = 'wal-mart'
     WHERE r.name = r2.name)

小提琴演示

于 2013-08-15T21:44:33.537 回答
1

这是获得指定结果的一种方法。

如果您只想检查一两个食谱,则在内WHERE联视图查询中包含一个子句(在下面的查询中注释掉,它返回所有食谱。)如果您只想检查一两个商店,请在外部查询(在下面的查询中注释掉。)

 SELECT s.name AS store_name
      , r.name AS recipe_name
      , i.ri_count
  FROM  ( SELECT ri.name
               , COUNT(DISTINCT ri.ingredient) AS ri_count
            FROM recipes ri
        -- WHERE ri.name IN ('fried chicken','spaghetti')
           GROUP
              BY ri.name
         ) i
   JOIN recipes r
     ON r.name = i.name
   LEFT
   JOIN stores s
     ON s.ingredient = r.ingredient
 -- AND s.name IN ('target','wal-mart')
  GROUP
     BY s.name
      , r.name
 HAVING COUNT(DISTINCT s.ingredient) = i.ri_count
于 2013-08-15T22:56:24.410 回答
0

(对数据进行了一点改造,只使用数字键)

CREATE TABLE IF NOT EXISTS ingredients (
  ing_id INTEGER NOT NULL PRIMARY KEY
  , ing_name varchar(32) NOT NULL
) ;

INSERT INTO ingredients (ing_id, ing_name) VALUES
(1, 'apple' ),
(2, 'beef' ),
(3, 'cheese' ),
(4, 'chicken' ),
(5, 'eggs' ),
(6, 'flour' ),
(7, 'milk' ),
(8, 'pasta' ),
(9, 'sugar' ),
(10, 'tomato' );

CREATE TABLE IF NOT EXISTS recipes (
  rec_id INTEGER NOT NULL PRIMARY KEY
  , rec_name varchar(32) NOT NULL
 );

INSERT INTO recipes (rec_id, rec_name) VALUES
(1, 'apple pie' ) ,
(2, 'cheeseburger' ) ,
(3, 'fried chicken' ) ,
(4, 'spaghetti' ) ;

CREATE TABLE IF NOT EXISTS recipe_ingredient (
  rec_id INTEGER NOT NULL REFERENCES recipes(rec_id)
  , ing_id INTEGER NOT NULL REFERENCES ingredients (ing_id)
  , PRIMARY KEY (rec_id, ing_id)
 );

INSERT INTO recipe_ingredient (rec_id, ing_id) VALUES
(1, 1), (1, 6), (1, 7), (1, 9),
(2, 2), (2, 3), (2, 6), (2, 7),
(3, 4), (3, 6), (4, 2),
(4, 8), (4, 10);
8), (4, 10);

CREATE TABLE IF NOT EXISTS stores (
  sto_id INTEGER NOT NULL PRIMARY KEY
  , sto_name varchar(32) NOT NULL
 );

INSERT INTO stores (sto_id, sto_name) VALUES
(1, 'target' ),
(2, 'wal-mart' );

CREATE TABLE IF NOT EXISTS store_ingredient (
  sto_id INTEGER NOT NULL REFERENCES stores(sto_id)
  , ing_id INTEGER NOT NULL REFERENCES ingredients(ing_id)
  , PRIMARY KEY (sto_id, ing_id)
 );

INSERT INTO store_ingredient (sto_id, ing_id ) VALUES
(1, 1), (1, 4), (1, 6), (1, 7), (1, 9),
(2, 2), (2, 3), (2, 6), (2, 7), (2, 8), (2, 10)
        ;

查询以查找所有原料可由沃尔玛提供的所有食谱。

SELECT r.rec_name
        -- All the recipes
FROM recipes r
WHERE NOT EXISTS (
        SELECT *
        -- ... that do not contain any ingredient
        FROM recipe_ingredient ri
        WHERE ri.rec_id = r.rec_id
        AND NOT EXISTS (
                SELECT *
                -- ... that cannot be provided by wal-mart.
                FROM store_ingredient si
                JOIN stores s ON s.sto_id = si.sto_id
                WHERE si.ing_id = ri.ing_id
                 AND s.sto_name = 'wal-mart'
                )
        );
于 2013-08-16T09:45:22.490 回答
0

嗨,首先我想告诉你,你最好改进你的模型。尝试使其正常化。另一方面,如果我没有错,您需要执行以下操作:

SELECT GROUP_CONCAT(r.name SEPARATOR " & ") recipients
FROM stores s
JOIN ingredients i ON s.ingredient=i.id
JOIN recipes r ON r.ingredient=i.id
WHERE s.name="wal-mart"
GROUP BY r.ingredient

玩这个 http://sqlfiddle.com/#!2/3c763/27

于 2013-08-15T21:55:34.940 回答