(本文中SQL语句均在Mysql v5.1中验证)
mysql> select * from t1;
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
mysql> select * from t2;
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
| 2 | NULL | 100 |
| 3 | 5 | 80 |
| 4 | 11 | 11 |
| 6 | 5 | 80 |
| 7 | 5 | 5 |
+----+--------+--------+
6 rows in set (0.00 sec)
把所有执行结果再看一遍,把问题写上
*************************************** in ************************************************
SQL中,连接词 in 是用来测试“元组”是否是“集合”中的成员,即该元组是否属于指定集合。
其中,“元组”可以是由某个关系中的若干属性组成(如1等),或可由这些属性和一些常量组成(如2等),或者直接由若干常量组成(如4等)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)(如1等),或者由一些常量n元组构成此集合(如7,8等)。
需要注意的是,这个属于关系的判断要满足“元素”和“集合”的关系。如元素是一个二元组(如:(id, value)),则相对应的集合就应该是以二元组为元素的集合,(如:((id1, value1), (id2, value2),(id3, value3))),
这样才会形成一个有效的判断。由 select 语句返回的关系就是这样一个集合,该集合由若干属性构成的n元组组成。
实际上,in之前的元组的模式就是in之后的集合中元素的样子,(如12:in之前是一个三元组,则in之后的集合就是由若干三元组构成的)(又如21:in之前的元素是这个样子((1,10),(3,4)),则in之后的集合的元素就应该与它样子相同),这样才会在语法上不出问题。
(1)mysql> select * from t1 where (id, value1) in (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) in (select id, value1,value2 from t2);
Empty set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) in (select id, value1,value2 from t2);
Empty set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) in (1,10);
ERROR 1241 (21000): Operand should contain 2 column(s)
(7)mysql> select * from t1 where (id,value1) in ((1,10));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(8)mysql> select * from t1 where (id,value1) in ((1,10),(4,3));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(9)mysql> select * from t1 where (id,value1) in ((1,10),(4,5));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(10)mysql> select * from t1 where (id,value1,100) in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(11)mysql> select * from t1 where (id,value1,100) in ((1,10,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(12)mysql> select * from t1 where (id,value1,100) in ((1,10,100),(4,3,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(13)mysql> select * from t1 where (id,value1,100) in ((1,10,100),(4,5,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(14)mysql> select * from t1 where (1,10,100) in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(15)mysql> select * from t1 where (1,10,100) in ((1,10,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(16)mysql> select * from t1 where (1,10,100) in ((1,10,100),(4,3,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(17)mysql> select * from t1 where (1,10,100) in ((1,10,100),(4,5,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(18)mysql> select * from t1 where ((1,10),(3,4)) in ((1,10),(3,4));
ERROR 1241 (21000): Operand should contain 2 column(s)
(19)mysql> select * from t1 where ((1,10),(3,4)) in (((1,10),(3,4)));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(20)mysql> select * from t1 where ((1,10),(3,4)) in (((1,10),(3,5)));
Empty set (0.00 sec)
(21)mysql> select * from t1 where ((1,10),(3,4)) in (((1,10),(3,5)),((1,2),(3,4)));
Empty set (0.00 sec)
**********************************************************************************************
*************************************** not in ************************************************
not in 的执行说明与 in 完全相同,且这些SQL语句一一对应,部分互为补集。不互为补集的那部分是因为null值参与计算,从而造成了在做比较时产生了unknown值。
SQL中,连接词 not in 是用来测试“元组”是否不是“集合”中的成员,即该元组是否不属于指定集合。
其中,“元组”可以是由某个关系中的若干属性组成(如1等),或可由这些属性和一些常量组成(如2等),或者直接由若干常量组成(如4等)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)(如1等),或者由一些常量n元组构成此集合(如7,8等)。
需要注意的是,这个属于关系的判断要满足“元素”和“集合”的关系。如元素是一个二元组(如:(id, value)),则相对应的集合就应该是以二元组为元素的集合,(如:((id1, value1), (id2, value2),(id3, value3))),
这样才会形成一个有效的判断。由 select 语句返回的关系就是这样一个集合,该集合由若干属性构成的n元组组成。
实际上,in之前的元组的模式就是in之后的集合中元素的样子,(如12:in之前是一个三元组,则in之后的集合就是由若干三元组构成的)(又如21:in之前的元素是这个样子((1,10),(3,4)),则in之后的集合的元素就应该与它样子相同),这样才会在语法上不出问题。
(1)mysql> select * from t1 where (id, value1) not in (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) not in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) not in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) not in (select id, value1,value2 from t2);
Empty set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) not in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) not in (1,10);
ERROR 1241 (21000): Operand should contain 2 column(s)
(7)mysql> select * from t1 where (id,value1) not in ((1,10));
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
3 rows in set (0.00 sec)
(8)mysql> select * from t1 where (id,value1) not in ((1,10),(4,3));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
+----+--------+
1 row in set (0.00 sec)
(9)mysql> select * from t1 where (id,value1) not in ((1,10),(4,5));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(10)mysql> select * from t1 where (id,value1,100) not in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(11)mysql> select * from t1 where (id,value1,100) not in ((1,10,100));
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
3 rows in set (0.00 sec)
(12)mysql> select * from t1 where (id,value1,100) not in ((1,10,100),(4,3,100));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
+----+--------+
1 row in set (0.00 sec)
(13)mysql> select * from t1 where (id,value1,100) not in ((1,10,100),(4,5,100));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(14)mysql> select * from t1 where (1,10,100) not in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(15)mysql> select * from t1 where (1,10,100) not in ((1,10,100));
Empty set (0.00 sec)
(16)mysql> select * from t1 where (1,10,100) not in ((1,10,100),(4,3,100));
Empty set (0.00 sec)
(17)mysql> select * from t1 where (1,10,100) not in ((1,10,100),(4,5,100));
Empty set (0.00 sec)
(18)mysql> select * from t1 where ((1,10),(3,4)) not in ((1,10),(3,4));
ERROR 1241 (21000): Operand should contain 2 column(s)
(19)mysql> select * from t1 where ((1,10),(3,4)) not in (((1,10),(3,4)));
Empty set (0.00 sec)
(20)mysql> select * from t1 where ((1,10),(3,4)) not in (((1,10),(3,5)));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(21)mysql> select * from t1 where ((1,10),(3,4)) not in (((1,10),(3,5)),((1,2),(3,4)));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
**********************************************************************************************
****************************************** =some **********************************************
SQL中,连接词 =some 是用来测试“元组”是否至少与“集合”中的某一个成员相等,它与 in 等价,即判断该“元组”是否属于指定“集合”。
其中,“元组”可以是由某个关系中的若干属性组成(如1),或可由这些属性和一些常量组成(如2),或者直接由若干常量组成(如4)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)。
注意:与 in 和 not in 不同的是,=some 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如6)。
(1)mysql> select * from t1 where (id, value1) =some (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) =some (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) =some (select id, value1,value2 from t2);
Empty set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) =some (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) =some (select id, value1,value2 from t2);
Empty set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) =some ((1,10));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,10))' at line 1
**********************************************************************************************
***************************************** =any ************************************************
SQL中,连接词 =any 是用来测试“元组”是否至少与“集合”中的某一个成员相等,它与 =some 和 in 等价,即判断该“元组”是否属于指定“集合”。
其中,“元组”可以是由某个关系中的若干属性组成(如1),或可由这些属性和一些常量组成(如2),或者直接由若干常量组成(如4)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)。
注意:与 in 和 not in 不同的是,=any 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如6)。
(1)mysql> select * from t1 where (id, value1) =any (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) =any (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) =any (select id, value1,value2 from t2);
Empty set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) =any (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) =any (select id, value1,value2 from t2);
Empty set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) =any ((1,10));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,10))' at line 1
**********************************************************************************************
***************************************** <>all ************************************************
SQL中,连接词 <>all 是用来测试“元组”是否与“集合”中的所有成员都不相等,它与 not in 等价,即判断该“元组”是否不属于指定“集合”。
其中,“元组”可以是由某个关系中的若干属性组成(如1),或可由这些属性和一些常量组成(如2),或者直接由若干常量组成(如4)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)。
注意:与 in 和 not in 不同的是,<>all 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如6)。
(1)mysql> select * from t1 where (id, value1) <>all (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) <>all (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) <>all (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) <>all (select id, value1,value2 from t2);
Empty set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) <>all (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) <>all ((1,10));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,10))' at line 1
**********************************************************************************************
***************************************** <>some ************************************************
SQL中,连接词 <>some 是用来测试一个“属性”的值是否至少不等于一个指定“集合”中的对应成员。
其中,“属性”只能是单个属性,可以是由某个关系中的某个属性组成(如1),或者直接指定一个常量(如2)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列单属性元组组成)。
注意:与 =some 不同的是,<>some 前面只能指定一个属性,而且 <>some 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如3,4)。
(1)mysql> select * from t1 where id <>some (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(2)mysql> select * from t1 where 1 <>some (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1) <>some (select id, value1 from t2);
ERROR 1241 (21000): Operand should contain 1 column(s)
(4)mysql> select * from t1 where id <>some (1,1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
>some, >=some, <some, <=some 亦均只能对一个属性进行操作,否则报错:ERROR 1241 (21000): Operand should contain 1 column(s)
>some, >=some, <some, <=some 后面那个指定的集合,亦均只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
**********************************************************************************************
***************************************** <>any ************************************************
SQL中,连接词 <>any 是用来测试一个“属性”的值是否至少不等于一个指定“集合”中的对应成员。
其中,“属性”只能是单个属性,可以是由某个关系中的某个属性组成(如1),或者直接指定一个常量(如2)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列单属性元组组成)。
注意:与 =any 不同的是,<>any 前面只能指定一个属性,而且 <>any 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如3,4)。
(1)mysql> select * from t1 where id <>any (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(2)mysql> select * from t1 where 1 <>any (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1) <>any (select id, value1 from t2);
ERROR 1241 (21000): Operand should contain 1 column(s)
(4)mysql> select * from t1 where id <>any (1,1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
>any, >=any, <any, <=any 亦均只能对一个属性进行操作,否则报错:ERROR 1241 (21000): Operand should contain 1 column(s)
>any, >=any, <any, <=any 后面那个指定的集合,亦均只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
**********************************************************************************************
***************************************** =all ************************************************
SQL中,连接词 =all 是用来测试一个“属性”的值是否与指定“集合”中的所有对应成员相等。
其中,“属性”只能是单个属性,可以是由某个关系中的某个属性组成(如1),或者直接指定一个常量(如2)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列单属性元组组成)。
注意:与 <>any 不同的是,=all 前面只能指定一个属性,而且 =all 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如3,4)。
(1)mysql> select * from t1 where id =all (select id from t2);
Empty set (0.00 sec)
(2)mysql> select * from t1 where 1 =all (select id from t2);
Empty set (0.00 sec)
(3)mysql> select * from t1 where (id, value1) =all (select id, value1 from t2);
ERROR 1241 (21000): Operand should contain 1 column(s)
(4)mysql> select * from t1 where id =all (1,1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
>all, >=all, <all, <=all 亦均只能对一个属性进行操作,否则报错:ERROR 1241 (21000): Operand should contain 1 column(s)
>all, >=all, <all, <=all 后面那个指定的集合,亦均只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
**********************************************************************************************
以上三个 <>some, <>any, =all 中相应的 op+{some|any|all} 只能对一个属性进行操作的说明参见:
************************************ =,<>,>,>=,<,<= **********************************************************
=,<>,>,>=,<,<= 仅能对元组进行比较,而不能对元组和集合比较,所以在 where 从句中,如果要使用这些操作符,则 where 前后应均为元组,而不能为元组和集合。
而且 where 前如果是一个元组,而且 where 后使用了 select 语句,则该 select 语句也只有在返回单行数据时才可与该元组比较(如5),否则会报错(如6)。
(1)mysql> select * from t2 where (id, value1) = (1,10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
+----+--------+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t2 where (id,10) = (1,10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
+----+--------+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t2 where (id,11) = (1,10);
Empty set (0.00 sec)
(4)mysql> select * from t2 where (1,10) = (1,10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
| 2 | NULL | 100 |
| 3 | 5 | 80 |
| 4 | 11 | 11 |
| 6 | 5 | 80 |
| 7 | 5 | 5 |
+----+--------+--------+
6 rows in set (0.00 sec)
(5)mysql> select * from t2 where (id, value1) = (select * from t1 where id=1 and value1=10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
+----+--------+--------+
1 row in set (0.00 sec)
(6)mysql> select * from t2 where (id, value1) = (select * from t1);
ERROR 1242 (21000): Subquery returns more than 1 row
**********************************************************************************************
<b><i>几个说明:</i></b>
1.个人感觉 MySQL 中对 in(=some) 以及 not in(<>all) 的实现是这样的:
判断某元组对是否属于某关系:(a,b) in(=some) ((a1,b1),(a2,b2)......) (1)
实际上是将(1)转换为如下的方式
(1) => ((a,b)=(a1,b1)) ∨ ((a,b)=(a2,b2)) ∨ ......
=> (a=a1 ∧ b=b1) ∨ (a=a2 ∧ b=b2) ∨ ......
判断某元组对是否不属于某关系:(a,b) not in(<>all) ((a1,b1),(a2,b2)......) (2)
实际上是将(2)转换为如下的方式
(2) => ((a,b)≠(a1,b1)) ∧ ((a,b)≠(a2,b2)) ∧ ......
=> (a≠a1 ∨ b≠b1) ∧ (a≠a2 ∨ b≠b2) ∧ ......
之所以得出这个结论,是根据 not in 部分的sql语句1,3推导出来的。
not in.(1)中,结果集中没出现(2, NULL)是因为t1中的(2, NULL)在与t2中的(2, NULL)进行not in判断时得到的结果是unknown,故where语句未把t1中的(2, NULL)加入到结果集中。
(2≠2 ∨ NULL≠NULL) ∧ T ∧ ...... => (F ∨ unknown) ∧ T ∧ ...... => unknown
not in.(2)中,结果集中出现了(2, NULL)是因为(2, NULL, 101)在与t2中的(2, NULL, 100)进行not in判断时得到的结果是true,故where语句把t1中的(2, NULL)加入到了结果集中。
(2≠2 ∨ NULL≠NULL ∨ 100≠101) ∧ T ∧ ...... => (F ∨ unknown ∨ T) ∧ T ∧ ...... => (T) ∧ T ∧ ...... => T
可见,在判断not in是否成立时,元组中只要有任意一项不同即可认为它成立,即使该元组中含有NULL值。
所以如果将sql改为 select * from t1 where (id, value1,100) not in (select id, value1,value2 from t2); 所得结果仍然与not in.(1)相同。
<b><i>几个没搞清的问题:</i></b>
1.关于为何除了 =some, =any, <>all 之外的型如 op{ALL|ANY|SOME} 均不支持多属性的问题,在网上找到了个说法,摘录如下:
(网址为:http://www.5dlinux.com/article/6/2010/linux_39642.html)
·对于expr IN (subquery),expr可以是n-tuple(通过行构造程序语法指定),而且子查询能返回n-tuples个行。
·对于expr op {ALL|ANY|SOME} (subquery),expr必须是标度值,子查询必须是列子查询,不能返回多列行。
换句话讲,对于返回n-tuples行的子查询,
支持:(val_1, ..., val_n) IN (subquery)
但不支持:(val_1, ..., val_n) op {ALL|ANY|SOME} (subquery)
支持针对IN的行比较,但不支持针对其他的行比较,原因在于,IN实施是通过将其重新编写为“=”比较和AND操作的序列完成的。该方法不能用于ALL、ANY或SOME。
但在实际运行运行中,我们发现其实 =some, =any, <>all 也是可以针对多个属性进行的,不知是 MySQL 进行了改进还是怎么的。
<font color="red">但除了上面三个特例之外,其他的型如 expr op {ALL|ANY|SOME} (subquery) 的查询为何不支持多列还是不太清楚。</font>
2. not in 中的 7 vs 8,9 以及 11 vs 12,13 的问题。
我将这几个sql分了两组,分别为 7 vs 8,9 以及 11 vs 12,13. 这两组的问题其实都一样,那就是为何7,11的结果集中有(2, NULL),
而8,9,12,13的结果集却全都没有,难道仅仅是因为后者(8,9,12,13)比前者(7,11)多出来了一个常量元组?
经过试验,即使(1)改变后者中两个元组的前后位置;(2)增加后者中的元组个数;(2, NULL)都仍然不显示在结果集当中。
如执行:
mysql> select * from t1 where (id,value1) not in ((4,5),(1,10));
mysql> select * from t1 where (id,value1) not in ((4,5),(1,10),(100,200));
mysql> select * from t1 where (id,value1) not in ((1,10),(4,5),(100,200));
结果仍均为:
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
但是,如果将 not in 后面的常量元组改为由 select 返回的,则(2, NULL)可正常显示在结果集当中。
mysql> select * from t1 where (id,value1) not in (select * from t3);
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
其中表 t3 为:
mysql> select * from t3;
+------+--------+
| id | value1 |
+------+--------+
| 1 | 10 |
| 4 | 5 |
+------+--------+
若将 t3 变成仅含一行,再执行该语句,(2, NULL)仍可正常显示在结果集当中。
mysql> select * from t3;
+------+--------+
| id | value1 |
+------+--------+
| 1 | 10 |
+------+--------+
mysql> select * from t1 where (id,value1) not in (select * from t3);
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
原因为何,百思不得其解,如果有人知道,麻烦请告知,多谢!
mysql> select * from t1;
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
mysql> select * from t2;
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
| 2 | NULL | 100 |
| 3 | 5 | 80 |
| 4 | 11 | 11 |
| 6 | 5 | 80 |
| 7 | 5 | 5 |
+----+--------+--------+
6 rows in set (0.00 sec)
把所有执行结果再看一遍,把问题写上
*************************************** in ************************************************
SQL中,连接词 in 是用来测试“元组”是否是“集合”中的成员,即该元组是否属于指定集合。
其中,“元组”可以是由某个关系中的若干属性组成(如1等),或可由这些属性和一些常量组成(如2等),或者直接由若干常量组成(如4等)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)(如1等),或者由一些常量n元组构成此集合(如7,8等)。
需要注意的是,这个属于关系的判断要满足“元素”和“集合”的关系。如元素是一个二元组(如:(id, value)),则相对应的集合就应该是以二元组为元素的集合,(如:((id1, value1), (id2, value2),(id3, value3))),
这样才会形成一个有效的判断。由 select 语句返回的关系就是这样一个集合,该集合由若干属性构成的n元组组成。
实际上,in之前的元组的模式就是in之后的集合中元素的样子,(如12:in之前是一个三元组,则in之后的集合就是由若干三元组构成的)(又如21:in之前的元素是这个样子((1,10),(3,4)),则in之后的集合的元素就应该与它样子相同),这样才会在语法上不出问题。
(1)mysql> select * from t1 where (id, value1) in (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) in (select id, value1,value2 from t2);
Empty set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) in (select id, value1,value2 from t2);
Empty set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) in (1,10);
ERROR 1241 (21000): Operand should contain 2 column(s)
(7)mysql> select * from t1 where (id,value1) in ((1,10));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(8)mysql> select * from t1 where (id,value1) in ((1,10),(4,3));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(9)mysql> select * from t1 where (id,value1) in ((1,10),(4,5));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(10)mysql> select * from t1 where (id,value1,100) in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(11)mysql> select * from t1 where (id,value1,100) in ((1,10,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(12)mysql> select * from t1 where (id,value1,100) in ((1,10,100),(4,3,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(13)mysql> select * from t1 where (id,value1,100) in ((1,10,100),(4,5,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(14)mysql> select * from t1 where (1,10,100) in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(15)mysql> select * from t1 where (1,10,100) in ((1,10,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(16)mysql> select * from t1 where (1,10,100) in ((1,10,100),(4,3,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(17)mysql> select * from t1 where (1,10,100) in ((1,10,100),(4,5,100));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(18)mysql> select * from t1 where ((1,10),(3,4)) in ((1,10),(3,4));
ERROR 1241 (21000): Operand should contain 2 column(s)
(19)mysql> select * from t1 where ((1,10),(3,4)) in (((1,10),(3,4)));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(20)mysql> select * from t1 where ((1,10),(3,4)) in (((1,10),(3,5)));
Empty set (0.00 sec)
(21)mysql> select * from t1 where ((1,10),(3,4)) in (((1,10),(3,5)),((1,2),(3,4)));
Empty set (0.00 sec)
**********************************************************************************************
*************************************** not in ************************************************
not in 的执行说明与 in 完全相同,且这些SQL语句一一对应,部分互为补集。不互为补集的那部分是因为null值参与计算,从而造成了在做比较时产生了unknown值。
SQL中,连接词 not in 是用来测试“元组”是否不是“集合”中的成员,即该元组是否不属于指定集合。
其中,“元组”可以是由某个关系中的若干属性组成(如1等),或可由这些属性和一些常量组成(如2等),或者直接由若干常量组成(如4等)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)(如1等),或者由一些常量n元组构成此集合(如7,8等)。
需要注意的是,这个属于关系的判断要满足“元素”和“集合”的关系。如元素是一个二元组(如:(id, value)),则相对应的集合就应该是以二元组为元素的集合,(如:((id1, value1), (id2, value2),(id3, value3))),
这样才会形成一个有效的判断。由 select 语句返回的关系就是这样一个集合,该集合由若干属性构成的n元组组成。
实际上,in之前的元组的模式就是in之后的集合中元素的样子,(如12:in之前是一个三元组,则in之后的集合就是由若干三元组构成的)(又如21:in之前的元素是这个样子((1,10),(3,4)),则in之后的集合的元素就应该与它样子相同),这样才会在语法上不出问题。
(1)mysql> select * from t1 where (id, value1) not in (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) not in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) not in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) not in (select id, value1,value2 from t2);
Empty set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) not in (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) not in (1,10);
ERROR 1241 (21000): Operand should contain 2 column(s)
(7)mysql> select * from t1 where (id,value1) not in ((1,10));
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
3 rows in set (0.00 sec)
(8)mysql> select * from t1 where (id,value1) not in ((1,10),(4,3));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
+----+--------+
1 row in set (0.00 sec)
(9)mysql> select * from t1 where (id,value1) not in ((1,10),(4,5));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(10)mysql> select * from t1 where (id,value1,100) not in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(11)mysql> select * from t1 where (id,value1,100) not in ((1,10,100));
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
3 rows in set (0.00 sec)
(12)mysql> select * from t1 where (id,value1,100) not in ((1,10,100),(4,3,100));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
+----+--------+
1 row in set (0.00 sec)
(13)mysql> select * from t1 where (id,value1,100) not in ((1,10,100),(4,5,100));
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(14)mysql> select * from t1 where (1,10,100) not in (1,10,100);
ERROR 1241 (21000): Operand should contain 3 column(s)
(15)mysql> select * from t1 where (1,10,100) not in ((1,10,100));
Empty set (0.00 sec)
(16)mysql> select * from t1 where (1,10,100) not in ((1,10,100),(4,3,100));
Empty set (0.00 sec)
(17)mysql> select * from t1 where (1,10,100) not in ((1,10,100),(4,5,100));
Empty set (0.00 sec)
(18)mysql> select * from t1 where ((1,10),(3,4)) not in ((1,10),(3,4));
ERROR 1241 (21000): Operand should contain 2 column(s)
(19)mysql> select * from t1 where ((1,10),(3,4)) not in (((1,10),(3,4)));
Empty set (0.00 sec)
(20)mysql> select * from t1 where ((1,10),(3,4)) not in (((1,10),(3,5)));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(21)mysql> select * from t1 where ((1,10),(3,4)) not in (((1,10),(3,5)),((1,2),(3,4)));
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
**********************************************************************************************
****************************************** =some **********************************************
SQL中,连接词 =some 是用来测试“元组”是否至少与“集合”中的某一个成员相等,它与 in 等价,即判断该“元组”是否属于指定“集合”。
其中,“元组”可以是由某个关系中的若干属性组成(如1),或可由这些属性和一些常量组成(如2),或者直接由若干常量组成(如4)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)。
注意:与 in 和 not in 不同的是,=some 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如6)。
(1)mysql> select * from t1 where (id, value1) =some (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) =some (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) =some (select id, value1,value2 from t2);
Empty set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) =some (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) =some (select id, value1,value2 from t2);
Empty set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) =some ((1,10));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,10))' at line 1
**********************************************************************************************
***************************************** =any ************************************************
SQL中,连接词 =any 是用来测试“元组”是否至少与“集合”中的某一个成员相等,它与 =some 和 in 等价,即判断该“元组”是否属于指定“集合”。
其中,“元组”可以是由某个关系中的若干属性组成(如1),或可由这些属性和一些常量组成(如2),或者直接由若干常量组成(如4)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)。
注意:与 in 和 not in 不同的是,=any 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如6)。
(1)mysql> select * from t1 where (id, value1) =any (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) =any (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
+----+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) =any (select id, value1,value2 from t2);
Empty set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) =any (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) =any (select id, value1,value2 from t2);
Empty set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) =any ((1,10));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,10))' at line 1
**********************************************************************************************
***************************************** <>all ************************************************
SQL中,连接词 <>all 是用来测试“元组”是否与“集合”中的所有成员都不相等,它与 not in 等价,即判断该“元组”是否不属于指定“集合”。
其中,“元组”可以是由某个关系中的若干属性组成(如1),或可由这些属性和一些常量组成(如2),或者直接由若干常量组成(如4)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列n元组组成)。
注意:与 in 和 not in 不同的是,<>all 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如6)。
(1)mysql> select * from t1 where (id, value1) <>all (select id, value1 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(2)mysql> select * from t1 where (id, value1,100) <>all (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
2 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1,101) <>all (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(4)mysql> select * from t1 where (3,5,80) <>all (select id, value1,value2 from t2);
Empty set (0.00 sec)
(5)mysql> select * from t1 where (3,5,81) <>all (select id, value1,value2 from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(6)mysql> select * from t1 where (id,value1) <>all ((1,10));
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,10))' at line 1
**********************************************************************************************
***************************************** <>some ************************************************
SQL中,连接词 <>some 是用来测试一个“属性”的值是否至少不等于一个指定“集合”中的对应成员。
其中,“属性”只能是单个属性,可以是由某个关系中的某个属性组成(如1),或者直接指定一个常量(如2)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列单属性元组组成)。
注意:与 =some 不同的是,<>some 前面只能指定一个属性,而且 <>some 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如3,4)。
(1)mysql> select * from t1 where id <>some (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(2)mysql> select * from t1 where 1 <>some (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1) <>some (select id, value1 from t2);
ERROR 1241 (21000): Operand should contain 1 column(s)
(4)mysql> select * from t1 where id <>some (1,1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
>some, >=some, <some, <=some 亦均只能对一个属性进行操作,否则报错:ERROR 1241 (21000): Operand should contain 1 column(s)
>some, >=some, <some, <=some 后面那个指定的集合,亦均只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
**********************************************************************************************
***************************************** <>any ************************************************
SQL中,连接词 <>any 是用来测试一个“属性”的值是否至少不等于一个指定“集合”中的对应成员。
其中,“属性”只能是单个属性,可以是由某个关系中的某个属性组成(如1),或者直接指定一个常量(如2)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列单属性元组组成)。
注意:与 =any 不同的是,<>any 前面只能指定一个属性,而且 <>any 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如3,4)。
(1)mysql> select * from t1 where id <>any (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(2)mysql> select * from t1 where 1 <>any (select id from t2);
+----+--------+
| id | value1 |
+----+--------+
| 1 | 10 |
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
4 rows in set (0.00 sec)
(3)mysql> select * from t1 where (id, value1) <>any (select id, value1 from t2);
ERROR 1241 (21000): Operand should contain 1 column(s)
(4)mysql> select * from t1 where id <>any (1,1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
>any, >=any, <any, <=any 亦均只能对一个属性进行操作,否则报错:ERROR 1241 (21000): Operand should contain 1 column(s)
>any, >=any, <any, <=any 后面那个指定的集合,亦均只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
**********************************************************************************************
***************************************** =all ************************************************
SQL中,连接词 =all 是用来测试一个“属性”的值是否与指定“集合”中的所有对应成员相等。
其中,“属性”只能是单个属性,可以是由某个关系中的某个属性组成(如1),或者直接指定一个常量(如2)。
“集合”可以是由 select 语句返回的关系(这个关系是由一系列单属性元组组成)。
注意:与 <>any 不同的是,=all 前面只能指定一个属性,而且 =all 后面那个指定的集合,只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错(如3,4)。
(1)mysql> select * from t1 where id =all (select id from t2);
Empty set (0.00 sec)
(2)mysql> select * from t1 where 1 =all (select id from t2);
Empty set (0.00 sec)
(3)mysql> select * from t1 where (id, value1) =all (select id, value1 from t2);
ERROR 1241 (21000): Operand should contain 1 column(s)
(4)mysql> select * from t1 where id =all (1,1);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
>all, >=all, <all, <=all 亦均只能对一个属性进行操作,否则报错:ERROR 1241 (21000): Operand should contain 1 column(s)
>all, >=all, <all, <=all 后面那个指定的集合,亦均只能是由 select 语句返回的关系,而不能由一些常量n元组构成,否则会报错:ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '1,1)' at line 1
**********************************************************************************************
以上三个 <>some, <>any, =all 中相应的 op+{some|any|all} 只能对一个属性进行操作的说明参见:
************************************ =,<>,>,>=,<,<= **********************************************************
=,<>,>,>=,<,<= 仅能对元组进行比较,而不能对元组和集合比较,所以在 where 从句中,如果要使用这些操作符,则 where 前后应均为元组,而不能为元组和集合。
而且 where 前如果是一个元组,而且 where 后使用了 select 语句,则该 select 语句也只有在返回单行数据时才可与该元组比较(如5),否则会报错(如6)。
(1)mysql> select * from t2 where (id, value1) = (1,10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
+----+--------+--------+
1 row in set (0.00 sec)
(2)mysql> select * from t2 where (id,10) = (1,10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
+----+--------+--------+
1 row in set (0.00 sec)
(3)mysql> select * from t2 where (id,11) = (1,10);
Empty set (0.00 sec)
(4)mysql> select * from t2 where (1,10) = (1,10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
| 2 | NULL | 100 |
| 3 | 5 | 80 |
| 4 | 11 | 11 |
| 6 | 5 | 80 |
| 7 | 5 | 5 |
+----+--------+--------+
6 rows in set (0.00 sec)
(5)mysql> select * from t2 where (id, value1) = (select * from t1 where id=1 and value1=10);
+----+--------+--------+
| id | value1 | value2 |
+----+--------+--------+
| 1 | 10 | 100 |
+----+--------+--------+
1 row in set (0.00 sec)
(6)mysql> select * from t2 where (id, value1) = (select * from t1);
ERROR 1242 (21000): Subquery returns more than 1 row
**********************************************************************************************
<b><i>几个说明:</i></b>
1.个人感觉 MySQL 中对 in(=some) 以及 not in(<>all) 的实现是这样的:
判断某元组对是否属于某关系:(a,b) in(=some) ((a1,b1),(a2,b2)......) (1)
实际上是将(1)转换为如下的方式
(1) => ((a,b)=(a1,b1)) ∨ ((a,b)=(a2,b2)) ∨ ......
=> (a=a1 ∧ b=b1) ∨ (a=a2 ∧ b=b2) ∨ ......
判断某元组对是否不属于某关系:(a,b) not in(<>all) ((a1,b1),(a2,b2)......) (2)
实际上是将(2)转换为如下的方式
(2) => ((a,b)≠(a1,b1)) ∧ ((a,b)≠(a2,b2)) ∧ ......
=> (a≠a1 ∨ b≠b1) ∧ (a≠a2 ∨ b≠b2) ∧ ......
之所以得出这个结论,是根据 not in 部分的sql语句1,3推导出来的。
not in.(1)中,结果集中没出现(2, NULL)是因为t1中的(2, NULL)在与t2中的(2, NULL)进行not in判断时得到的结果是unknown,故where语句未把t1中的(2, NULL)加入到结果集中。
(2≠2 ∨ NULL≠NULL) ∧ T ∧ ...... => (F ∨ unknown) ∧ T ∧ ...... => unknown
not in.(2)中,结果集中出现了(2, NULL)是因为(2, NULL, 101)在与t2中的(2, NULL, 100)进行not in判断时得到的结果是true,故where语句把t1中的(2, NULL)加入到了结果集中。
(2≠2 ∨ NULL≠NULL ∨ 100≠101) ∧ T ∧ ...... => (F ∨ unknown ∨ T) ∧ T ∧ ...... => (T) ∧ T ∧ ...... => T
可见,在判断not in是否成立时,元组中只要有任意一项不同即可认为它成立,即使该元组中含有NULL值。
所以如果将sql改为 select * from t1 where (id, value1,100) not in (select id, value1,value2 from t2); 所得结果仍然与not in.(1)相同。
<b><i>几个没搞清的问题:</i></b>
1.关于为何除了 =some, =any, <>all 之外的型如 op{ALL|ANY|SOME} 均不支持多属性的问题,在网上找到了个说法,摘录如下:
(网址为:http://www.5dlinux.com/article/6/2010/linux_39642.html)
·对于expr IN (subquery),expr可以是n-tuple(通过行构造程序语法指定),而且子查询能返回n-tuples个行。
·对于expr op {ALL|ANY|SOME} (subquery),expr必须是标度值,子查询必须是列子查询,不能返回多列行。
换句话讲,对于返回n-tuples行的子查询,
支持:(val_1, ..., val_n) IN (subquery)
但不支持:(val_1, ..., val_n) op {ALL|ANY|SOME} (subquery)
支持针对IN的行比较,但不支持针对其他的行比较,原因在于,IN实施是通过将其重新编写为“=”比较和AND操作的序列完成的。该方法不能用于ALL、ANY或SOME。
但在实际运行运行中,我们发现其实 =some, =any, <>all 也是可以针对多个属性进行的,不知是 MySQL 进行了改进还是怎么的。
<font color="red">但除了上面三个特例之外,其他的型如 expr op {ALL|ANY|SOME} (subquery) 的查询为何不支持多列还是不太清楚。</font>
2. not in 中的 7 vs 8,9 以及 11 vs 12,13 的问题。
我将这几个sql分了两组,分别为 7 vs 8,9 以及 11 vs 12,13. 这两组的问题其实都一样,那就是为何7,11的结果集中有(2, NULL),
而8,9,12,13的结果集却全都没有,难道仅仅是因为后者(8,9,12,13)比前者(7,11)多出来了一个常量元组?
经过试验,即使(1)改变后者中两个元组的前后位置;(2)增加后者中的元组个数;(2, NULL)都仍然不显示在结果集当中。
如执行:
mysql> select * from t1 where (id,value1) not in ((4,5),(1,10));
mysql> select * from t1 where (id,value1) not in ((4,5),(1,10),(100,200));
mysql> select * from t1 where (id,value1) not in ((1,10),(4,5),(100,200));
结果仍均为:
+----+--------+
| id | value1 |
+----+--------+
| 3 | 10 |
| 4 | 3 |
+----+--------+
但是,如果将 not in 后面的常量元组改为由 select 返回的,则(2, NULL)可正常显示在结果集当中。
mysql> select * from t1 where (id,value1) not in (select * from t3);
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
其中表 t3 为:
mysql> select * from t3;
+------+--------+
| id | value1 |
+------+--------+
| 1 | 10 |
| 4 | 5 |
+------+--------+
若将 t3 变成仅含一行,再执行该语句,(2, NULL)仍可正常显示在结果集当中。
mysql> select * from t3;
+------+--------+
| id | value1 |
+------+--------+
| 1 | 10 |
+------+--------+
mysql> select * from t1 where (id,value1) not in (select * from t3);
+----+--------+
| id | value1 |
+----+--------+
| 2 | NULL |
| 3 | 10 |
| 4 | 3 |
+----+--------+
原因为何,百思不得其解,如果有人知道,麻烦请告知,多谢!