【问题标题】:Multiple row conditions in WHERE clauseWHERE 子句中的多行条件
【发布时间】:2015-02-25 17:34:48
【问题描述】:

我在 MySQL 中编写以下查询时遇到问题。我有一个名为pizz0r_pizza_ingredients 的表,看起来像这样:

| id | pizza_id | ingredient | amount | measure |
+----+----------+------------+--------+---------+
| 6  |    1     |    15      |   3    |    4    |
|178 |    17    |    1       |   160  |    1    |
| 3  |    1     |    20      |   3    |    4    |

我想搜索对成分有特定要求的比萨,例如:

SELECT `pizza_id` 
FROM `pizz0r_pizza_ingredients` 
WHERE `ingredient` = 15 AND `ingredient` != 20 
GROUP BY `pizza_id`

我正在尝试获取 ingredient 等于 15 的条目,但如果它也有成分 20,则忽略该 Pizza_id。

当前结果是1,但在本例中不应返回任何内容。

【问题讨论】:

  • 为了我正确理解你,你的场景类似于“告诉我所有含有成分 15(比如辣椒)但不是成分 20(比如意大利辣香肠)或成分 21(比如,火腿)”?
  • 我认为您应该澄清您当前的结果是1,但您不希望它作为您的结果,对吧?因为1 有成分20?
  • 没错@RowlandShaw
  • @McAdam331 是的。我真正的桌子上的 Ofc 比萨饼多了很多
  • @Mcadam331 我想编辑它,但你的速度更快,谢谢

标签: mysql sql join group-by relational-division


【解决方案1】:

我喜欢使用group byhaving 来处理这些问题:

SELECT `pizza_id` 
FROM `pizz0r_pizza_ingredients` 
GROUP BY `pizza_id`
HAVING SUM(ingredient = 15) > 0 AND
       SUM(ingredient = 20) = 0;

您可以根据需要添加任意数量的新要求。 SUM() 表达式计算某种类型的成分的数量。 > 0 表示披萨上至少有一个。 = 0 表示没有。

【讨论】:

  • 从未像这样使用过SUM。谢谢。
  • 感谢@Gordon Linnof 这个似乎也比 Saharsh Shah 的解决方案更优雅、更快!
【解决方案2】:

试试这个:

SELECT P1.pizza_id 
FROM pizz0r_pizza_ingredients P1 
LEFT OUTER JOIN pizz0r_pizza_ingredients P2 ON P1.pizza_id = P2.pizza_id AND P2.ingredient IN (20, 21)
WHERE P1.ingredient = 15 AND P2.id IS NULL
GROUP bY P1.pizza_id;

【讨论】:

  • where 子句中 p2.id 上的过滤器是否为 null 会创建隐式内部连接?
  • @DanBracuk 它不会创建内部连接。它将从 A 表中获取不匹配的记录到 B 表
  • 非常感谢,现在可以了。虽然我不完全理解它,我会用这个。
【解决方案3】:

您需要结合两组数据 - 您可能想要的所有数据,然后排除那些与您不需要的成分相交的数据,例如:

SELECT DISTINCT
            wanted.pizza_id

FROM        pizz0r_pizza_ingredients wanted 

LEFT JOIN   pizz0r_pizza_ingredients dontwant
    ON      wanted.pizza_id = dontwant.pizza_id
    AND     dontwant.ingredient IN ( 20, 21 )

WHERE       wanted.ingredient IN ( 15 ) -- You could have multiples, if you wanted ham OR chicken, for example
    AND     dontwant.pizza_id IS NULL -- No bad ingredients

【讨论】:

  • 这也有效,对我来说看起来更干净非常感谢你们,你们很快!
【解决方案4】:

编辑:您的问题之前不清楚。如果您想排除成分为 20 的比萨饼,可以使用以下方法:

select pizzaid from pizz0r_pizza_ingredients where ingredient = 15
EXCEPT
select pizzaid from pizz0r_pizza_ingredients where ingredient != 20

注意:EXCEPT 通常比 joinnot in 快​​

【讨论】:

  • 谢谢,但这不是我想要的。我不想要这个或者我想要一个 Pizza_id 的两个要求。我有点难以描述。
  • Im gettin mysql error #1064 with this one,我猜我的版本无法识别除了。无论如何,谢谢,我在上面得到了一个可行的建议。
  • 我认为 MySQL 根本不支持 EXCEPT。
  • @StephanWahlen,我错了,MySQL 不支持EXCEPT。感谢@McAdam331 指出这一点。不过很可惜。
【解决方案5】:

您有一个选择是为此使用子查询。为了更好地理解这一点,我会先将两个查询分开,然后将它们组合起来。

第一个将拉出所有具有成分 15 的 pizza_id

SELECT DISTINCT pizza_id
FROM myTable
WHERE ingredient = 15;

然后,您可以编写另一个搜索 Pizza_id 其中成分等于 20 的代码:

SELECT DISTINCT pizza_id
FROM myTable
WHERE ingredient = 20;

最后,您可以使用NOT IN 子句将两者结合起来。也就是说,你可以选择所有满足第一个条件的pizza_id,其中id不在满足第二个条件的pizza_ids中:

SELECT DISTINCT pizza_id
FROM myTable
WHERE ingredient = 15 AND pizza_id NOT IN(
  SELECT DISTINCT pizza_id
  FROM myTable
  WHERE ingredient = 20);

编辑

这是SQL Fiddle

编辑 2

这是一个称为关系划分的主题。还有一个类似here的例子。

【讨论】:

  • 不,这不会返回1
  • @Sourav_Agasti 它不应该返回1
猜你喜欢
  • 2013-03-30
  • 1970-01-01
  • 2015-09-29
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 2015-07-07
相关资源
最近更新 更多