2011-08-08 17 views
4

我刚刚使用MySQL的IN解决了一个有趣的问题,但我不知道这个“技巧”被称为什么。MySQL IN条款的特殊性

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

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

我不知道expr IN(value,...),如根据dev.mysql.comexprvalue可以是多个列。

这是什么叫,还有更多像这样的快捷方式?
更重要的是 - 有没有办法将此查询转换为匹配skilllevel为“大于或等于”?


解决方案按照@yokoloko(虽然他也不会承认的)

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

回答

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 
    ) 

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

+0

是有道理的,但因为在比较平等,仍然是行不通的 – Mikhail

+0

哦一年你是对的:)我的坏 – yokoloko

+0

我相信,如果你只是删除了' skilllevel'来自'IN'和'level' from SELECT - 整个查询将起作用,因为如果级别不匹配,则不会返回'name' – Mikhail

2

这就是所谓的row subquery

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

+0

行子查询,当然不是生的。 (不能编辑少于6个字符) – yokoloko

+0

我编辑了错字。 'S /生/行/' –

+0

@yokoloko哎呀对不起,谢谢 –

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 

史密斯比安德森大,但代理人不比托马斯大。不过,我们知道如何在电话簿中排列这两个名字。

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