在mysql的'WHERE'子句中评估多个'IN'表达式

时间:2009-07-28 14:00:23

标签: sql mysql where-clause evaluation

@Cesar的请求进行更新。希望我明白你想要什么,如果没有,请恢复。 Quassnoi。

如果我发出SQL这样的查询:SELECT * FROM TABLE_NAME WHERE b IN (2, 7) AND c IN (3, 9),我可以假设MySQL只匹配每个列表中具有相同编号的元素的对吗?

(2, 3)(7, 9),...?

例如,假设我们有一个这样的表:

 +----------+----------+----------+
 |    PK    |     b    |     c    |
 +----------+----------+----------+
 |     1    |     2    |     3    |
 +----------+----------+----------+
 |     2    |     5    |     4    |
 +----------+----------+----------+
 |     3    |     7    |     9    |
 +----------+----------+----------+
 |     4    |     7    |     4    |
 +----------+----------+----------+
 |     5    |     2    |     9    |
 +----------+----------+----------+

假设返回的行是13(而不是5)是否正确?

5 个答案:

答案 0 :(得分:21)

SELECT * FROM TABLE_NAME WHERE b IN(5,7) AND c IN(4,4)

此查询将返回行,其中b57,而c4

“成对评估”是什么意思?

<强>更新

我将在示例中再添加一行:

 +----------+----------+----------+
 |    PK    |     b    |     c    |
 +----------+----------+----------+
 |     1    |     2    |     3    |
 +----------+----------+----------+
 |     2    |     5    |     4    |
 +----------+----------+----------+
 |     3    |     7    |     9    |
 +----------+----------+----------+
 |     4    |     7    |     4    |
 +----------+----------+----------+
 |     5    |     2    |     9    |
 +----------+----------+----------+

如果要匹配整个集合,可以使用以下语法:

SELECT  *
FROM    table_name
WHERE   (b, c) IN ((2, 3), (7, 9))

这意味着:“同时返回b2c3的所有行,或b7 }和с同时为9。“

在上面的示例中,此查询将返回行13

但如果你反过来重写这个查询,就像这样:

SELECT  *
FROM    table_name
WHERE   b IN (2, 7)
        AND c IN (3, 9)

,这意味着“返回b27的所有行,而c39 )。

这将返回行135,因为行5满足第二个查询的条件,但不满足第一个查询的条件。

答案 1 :(得分:5)

第2行和第2行的返回4是正确的,尽管你选择(4,4)可能会让它更加混乱,因为它是多余的。 AND表示该行必须满足您的条件才能成为真。如果查询有WHERE b IN(5,7) AND c IN(4,9),则会返回第2,3和4行。

如果你想成对,你需要拥有所有的组合。例如,b IN(5,7) AND c IN(4,9)将产生(5,4),(5,9),(7,4)和(7,9)作为可行的组合,而不仅仅是(5,4)和(5) 7,9)

答案 2 :(得分:5)

您可以按顺序评估每个条件,它可以让您更好地了解这里发生的事情。您的查询声明应该选择所有值,其中b是5或7且c是4,所以让我们使用第一个条件(b IN (5,7))减少表:

 +----------+----------+----------+
 |    PK    |     b    |     c    |
 +----------+----------+----------+
 |     1    |     2    |     3    | < No match
 +----------+----------+----------+
 |     2    |     5    |     4    | < Match
 +----------+----------+----------+
 |     3    |     7    |     9    | < Match
 +----------+----------+----------+
 |     4    |     7    |     4    | < Match
 +----------+----------+----------+

现在,让我们评估下一个条件,两者都必须为真,以便选择一行(c IN (4,4),其基本上与c = 4相同):

 +----------+----------+----------+
 |    PK    |     b    |     c    |
 +----------+----------+----------+
 |     2    |     5    |     4    | < Match
 +----------+----------+----------+
 |     3    |     7    |     9    | < No match
 +----------+----------+----------+
 |     4    |     7    |     4    | < Match
 +----------+----------+----------+

其他一切都有效:

 +----------+----------+----------+
 |    PK    |     b    |     c    |
 +----------+----------+----------+
 |     2    |     5    |     4    |
 +----------+----------+----------+
 |     4    |     7    |     4    |
 +----------+----------+----------+

答案 3 :(得分:1)

是的,我相信你是对的。

有效地,'IN'可以被认为是(b = 5 OR b = 7)的简写。这不是“引擎盖下”的工作方式,但它是一种简单的思考方式。

对于大型表,多个“IN”子句将导致性能问题。

编辑:

上面的海报是正确的,c IN(4,4)是没有意义的。你可以很容易地说'AND c = 4'。

如果将子句转换为其逻辑等价物,则可以看出原因:

SELECT * FROM table WHERE(b = 5 OR b = 7)AND(c = 4 OR c = 4)

答案 4 :(得分:1)

您的示例并未准确说明您的问题,但多个IN子句彼此无关;它们像任何其他WHERE子句一样按顺序进行评估。

因此,以下查询

SELECT * FROM FOO WHERE b IN(5,7) AND c IN(4,8)

将匹配以下任何内容:

b  c
----
5  4
5  8
7  4
7  8

IN可以被视为简单比较或简单比较。这意味着之前的查询也可以写成(机制略有不同,但概念是相同的):

SELECT * FROM FOO WHERE (b = 5 OR b = 7) AND (c = 4 OR c = 8)

所以,在你的例子中,是的,返回的唯一行是2和4.但这并不是你想的原因。