MySQL的IN子句的特性

时间:2011-08-08 17:40:31

标签: mysql optimization

我刚刚使用MySQL的IN解决了一个有趣的问题,但我不知道这个“技巧”是什么。

在我的设计中,我需要过滤掉不需要特定技能的行,或者满足技能名称和技能等级的行。这是解决方案:

SELECT * FROM table WHERE
    skillname = "" OR
    (skillname, skilllevel) IN (
        SELECT name, level FROM skills WHERE user="Mikhail"
    )

我不知道 expr IN(value,...),根据dev.mysql.com同时expr和{ {1}}可以是多列。

这叫什么,有更多这样的捷径吗?
更重要的是 - 有没有办法将此查询转换为匹配value为“大于或等于”?


根据@yokoloko

解决方案(虽然他不会承认)

skilllevel

3 个答案:

答案 0 :(得分:3)

抱歉,IN谓词始终会比较相等的值,不大于或等于。

以下是我写的方式:

SELECT table.* 
FROM table WHERE skillname = ''
UNION ALL
SELECT table.* 
FROM table JOIN skills 
  ON table.skillname = skills.name AND table.skilllevel >= skills.level
WHERE skills.user = 'Mikhail'

对于查询的术语,@ guide指出您运行了行子查询,并使用行构造函数语法将其与文字行进行了比较。 SQL允许您使用列,表达式或值创建匿名行,并在某些情况下使用它们,例如与具有兼容列数的另一行进行比较。我称之为行比较

你也可以在连接条件中使用它,但是如果你想要一个列的相等比较和另一个列的不等式,它真的不清楚:

SELECT table.* 
FROM table JOIN skills 
  ON (table.skillname, table.skilllevel) >= (skills.name, skills.level)
WHERE skills.user = 'Mikhail'

以上可能不会做你想要的。例如:

SELECT (1,2) = (1,2);   -- returns true (i.e. 1 in MySQL)

SELECT (1,2) >= (1,2);  -- returns true

SELECT (1,3) >= (1,2);  -- returns true

SELECT (1,2) >= (1,3);  -- returns false

SELECT (2,3) >= (1,2);  -- returns true

SELECT (1,3) >= (2,2);  -- returns false

相同的比较运算符应用于这些行中的所有列。但它也有短路(与AND不同):

SELECT (2,3) >= (1,4);  -- returns true

2大于1,但3不大于4.令人困惑?考虑一个字母顺序的例子:

SELECT ('Smith', 'Agent') >= ('Anderson', 'Thomas'); -- returns true
史密斯比安德森更伟大,但特工并不比托马斯大。不过,我们知道如何在电话簿中订购这两个名字。

所有这一切的要点是,如果你想要更多地控制比较,你需要编写完整的布尔表达式。

答案 1 :(得分:2)

这叫做row subquery

  

行子查询是一个子查询变体,它返回一行并且可以   因此返回多个列值。

答案 2 :(得分:0)

我不知道它是如何调用的,但如果我理解得很清楚你可以做这样的事情来获得更大的:

SELECT * FROM table t1 WHERE
    skillname = "" OR
    (skillname, skilllevel) IN (
        SELECT name, level FROM skills s WHERE user="Mikhail" and t1.skilllevel >= s.level
    )

但我不知道它是否真的很好地优化了。