SQL(ite)过滤一对多表

时间:2015-11-22 09:22:45

标签: sql sqlite

使用表格

CREATE TABLE recipeingredients(recipeid int, ingredientid int);
CREATE TABLE ingredients(ingredientid int primary key, name text, perishable int);

成分

1    'ingA'    0
2    'ingB'    1
3    'ingC'    1
4    'ingD'    0

recipeingredients

1    1
1    2
2    1
2    2
2    3
3    2
3    4
配料表用于存储配方可能具有的所有成分,而成分用于存储每种独特成分的质量。

我通过查询将配料添加到配料中:

SELECT * FROM recipeingredients
INNER JOIN (SELECT ingredientid, name, perishable FROM ingredients) i
ON recipeingredients.ingredientid = i.ingredientid

因为“易腐”'数据

现在,如果我想从选择中排除所有具有给定静态成分ID列表的食谱,我将如何进行呢?

我尝试了直观的选择

SELECT * FROM recipeingredients
INNER JOIN (SELECT ingredientid, name, perishable FROM ingredients
            WHERE ingredientid NOT IN (1, 3)
           ) i
ON recipeingredients.ingredientid = i.ingredientid

显然不起作用。

也就是说,这是我想要返回的那种选择,假设禁止的成分ID是1和3:

recipeid|ingredientid| name |perishable  
3     2     'ingB' 1
3     4     'ingD' 0

因为配方1和2都有1或3个。

我将如何进行此选择?我是否需要一个新的配料表来过滤配方ID?

1 个答案:

答案 0 :(得分:1)

如果两个列名都匹配,则不需要使用子查询来进行连接,并且可以使用USING子句简化连接:

SELECT recipeid,
       ingredientid,
       name,
       perishable
FROM recipeingredients
JOIN ingredients USING (ingredientid);

无论如何,SELECT ... FROM ingredients子查询中的WHERE子句返回列表中没有的所有成分。

如果要排除所有具有给定静态成分ID列表的配方,则必须在SQL中编写该配方。

此查询将选择具有给定的静态成分ID列表之一的所有配方ID:

SELECT DISTINCT recipeid
FROM recipeingredients
WHERE ingredientid IN (1, 3);

然后,此查询会从结果中排除这些食谱:

SELECT recipeid,
       ingredientid,
       name,
       perishable
FROM recipeingredients
JOIN ingredients USING (ingredientid)
WHERE recipeid NOT IN (SELECT recipeid
                       FROM recipeingredients
                       WHERE ingredientid IN (1, 3));