总结MySQL中的数据过滤方法:WHERE的基本过滤,WHERE的组合过滤,通配符过滤,子查询,组合查询。
1. WHERE的初级过滤
只检索所需数据需要指定搜索条件(search criteria),搜索条件也称为过滤条件(filter condition)。
mysql> SELECT prod_name,prod_price
-> FROM products
-> WHERE prod_price=2.50;
+---------------+------------+
| prod_name | prod_price |
+---------------+------------+
| Carrots | 2.50 |
| TNT (1 stick) | 2.50 |
+---------------+------------+
2 rows in set (0.88 sec)
除了上面提到的相等操作,还有WHERE通过其他操作符还能实现许多功能。
1.1 检查单个值
上面举了一个利用相等条件检查单个值的情况,下面再看一个利用不等条件的例子。
mysql> SELECT prod_name,prod_price
-> FROM products
-> WHERE prod_price > 50;
+--------------+------------+
| prod_name | prod_price |
+--------------+------------+
| JetPack 2000 | 55.00 |
+--------------+------------+
1 row in set (0.25 sec)
1.2 不匹配检查
列出不是由供应商1003制造的产品。
mysql> SELECT vend_id, prod_name
-> FROM products
-> WHERE vend_id <> 1003;
+---------+--------------+
| vend_id | prod_name |
+---------+--------------+
| 1001 | .5 ton anvil |
| 1001 | 1 ton anvil |
| 1001 | 2 ton anvil |
| 1002 | Fuses |
| 1005 | JetPack 1000 |
| 1005 | JetPack 2000 |
| 1002 | Oil can |
+---------+--------------+
7 rows in set (0.24 sec)
既可以使用<>
操作符,也可以使用!=
操作符。
1.3 范围值检查
为了检查某个范围的值,可使用BETWEEN操作符。下面展示,BETWEEN操作符检索价格在5美元和10美元之间的商品。
mysql> SELECT prod_name,prod_price
-> FROM products
-> WHERE prod_price BETWEEN 5 and 10;
+----------------+------------+
| prod_name | prod_price |
+----------------+------------+
| .5 ton anvil | 5.99 |
| 1 ton anvil | 9.99 |
| Bird seed | 10.00 |
| Oil can | 8.99 |
| TNT (5 sticks) | 10.00 |
+----------------+------------+
5 rows in set (0.75 sec)
在使用BETWEEN时需要跟在WHERE后面,必须指定两个值 ——所需范围的低端值和高端值。这两个值必须用AND关键字分隔。
1.4 空值检查
SELECT语句有一个特殊的WHERE子句,可用来检查具有NULL值的列。 这个WHERE子句就是IS NULL子句。
mysql> SELECT prod_name
-> From products
-> WHERE prod_price IS NULL;
Empty set (0.24 sec)
注意,不能使用相等条件来检查NULL,必须使用特殊语句。
2. WHERE的高级过滤
2.1 组合WHERE语句
使用AND操作符给WHERE子句附加条件。
mysql> SELECT prod_id,prod_price,vend_id
-> FROM products
-> WHERE vend_id=1003 AND prod_price<=10;
+---------+------------+---------+
| prod_id | prod_price | vend_id |
+---------+------------+---------+
| FB | 10.00 | 1003 |
| FC | 2.50 | 1003 |
| SLING | 4.49 | 1003 |
| TNT1 | 2.50 | 1003 |
| TNT2 | 10.00 | 1003 |
+---------+------------+---------+
5 rows in set (0.24 sec)
OR操作符与AND操作符不同,它指示MySQL检索匹配任一条件的行。
mysql> SELECT prod_id,prod_price,vend_id
-> FROM products
-> WHERE prod_price<5 OR vend_id=1001;
+---------+------------+---------+
| prod_id | prod_price | vend_id |
+---------+------------+---------+
| ANV01 | 5.99 | 1001 |
| ANV02 | 9.99 | 1001 |
| ANV03 | 14.99 | 1001 |
| FC | 2.50 | 1003 |
| FU1 | 3.42 | 1002 |
| SLING | 4.49 | 1003 |
| TNT1 | 2.50 | 1003 |
+---------+------------+---------+
7 rows in set (0.25 sec)
同时使用AND和OR时要注意:SQL在处理OR操作符前,优先处理AND操 作符。此问题的解决方法是使用圆括号明确地分组相应的操作符。
mysql> SELECT prod_id,prod_price,vend_id
-> FROM products
-> WHERE (vend_id=1003 OR vend_id=1002)AND prod_price<5;
+---------+------------+---------+
| prod_id | prod_price | vend_id |
+---------+------------+---------+
| FC | 2.50 | 1003 |
| FU1 | 3.42 | 1002 |
| SLING | 4.49 | 1003 |
| TNT1 | 2.50 | 1003 |
+---------+------------+---------+
4 rows in set (0.24 sec)
2.2 IN操作符
圆括号在WHERE子句中还有另外一种用法。IN操作符用来指定条件。
mysql> SELECT prod_price,prod_name,vend_id
-> From products
-> WHERE vend_id IN(1002,1005);
+------------+--------------+---------+
| prod_price | prod_name | vend_id |
+------------+--------------+---------+
| 3.42 | Fuses | 1002 |
| 35.00 | JetPack 1000 | 1005 |
| 55.00 | JetPack 2000 | 1005 |
| 8.99 | Oil can | 1002 |
+------------+--------------+---------+
4 rows in set (0.24 sec)
这并不表示范围,特别表示1002和1005这两个对象。相较于AND和OR更清晰直观。
2.3 NOT操作符
WHERE子句中的NOT操作符有且只有一个功能,那就是否定它之后所 跟的任何条件。
mysql> SELECT prod_price,prod_name,vend_id
-> From products
-> WHERE vend_id NOT IN(1002,1005);
+------------+----------------+---------+
| prod_price | prod_name | vend_id |
+------------+----------------+---------+
| 5.99 | .5 ton anvil | 1001 |
| 9.99 | 1 ton anvil | 1001 |
| 14.99 | 2 ton anvil | 1001 |
| 13.00 | Detonator | 1003 |
| 10.00 | Bird seed | 1003 |
| 2.50 | Carrots | 1003 |
| 50.00 | Safe | 1003 |
| 4.49 | Sling | 1003 |
| 2.50 | TNT (1 stick) | 1003 |
| 10.00 | TNT (5 sticks) | 1003 |
+------------+----------------+---------+
10 rows in set (0.24 sec)
3. 通配符过滤
前面提到:用SELECT搜索所有数据的时候,用到的*就是一个通配符除了这个符号还有两种比较常见的。
3.1 百分号%
%表示任何字符出现任意次数。例如,为了找出所有以词jet起头的产品,可使用以下SELECT 语句:
mysql> SELECT prod_price,prod_name,vend_id
-> From products
-> WHERE prod_name LIKE 'jet%';
+------------+--------------+---------+
| prod_price | prod_name | vend_id |
+------------+--------------+---------+
| 35.00 | JetPack 1000 | 1005 |
| 55.00 | JetPack 2000 | 1005 |
+------------+--------------+---------+
2 rows in set (0.54 sec)
此例子使用了搜索模式'jet%'
。在执行这条子句时,将检索任意以jet起头的词。%告诉MySQL接受jet之后的任意字符,不 管它有多少字符。 注意:按照MySQL的配置方式,搜索是区分大小写的。
通配符可在搜索模式中任意位置使用,并且可以使用多个通配符。
mysql> SELECT prod_price,prod_name,vend_id
-> From products
-> WHERE prod_name LIKE '%anvil%';
+------------+--------------+---------+
| prod_price | prod_name | vend_id |
+------------+--------------+---------+
| 5.99 | .5 ton anvil | 1001 |
| 9.99 | 1 ton anvil | 1001 |
| 14.99 | 2 ton anvil | 1001 |
+------------+--------------+---------+
3 rows in set (0.25 sec)
3.2 下划线 _
下划线只匹配单个字符而不是多个字符。 如下所示.5 ton anvi
的产品没有被匹配。
mysql> SELECT prod_price,prod_name,vend_id
-> From products
-> WHERE prod_name LIKE '_ ton anvil';
+------------+-------------+---------+
| prod_price | prod_name | vend_id |
+------------+-------------+---------+
| 9.99 | 1 ton anvil | 1001 |
| 14.99 | 2 ton anvil | 1001 |
+------------+-------------+---------+
2 rows in set (0.24 sec)
如果输入__ ton anvil
则只返回.5 ton anvil
那个产品。
4. 分组过滤
4.1 数据分组
分组是在SELECT语句的GROUP BY子句中建立的。下面的例子中我们利用COUNT
统计数据,分组。
mysql> SELECT vend_id, COUNT(*) AS num_probs
-> FROM products
-> GROUP BY vend_id;
+---------+-----------+
| vend_id | num_probs |
+---------+-----------+
| 1001 | 3 |
| 1002 | 2 |
| 1003 | 7 |
| 1005 | 2 |
+---------+-----------+
4 rows in set (0.55 sec)
GROUP BY子句有一些独特的地方
- GROUP BY子句可以包含任意数目的列。这使得能对分组进行嵌套, 为数据分组提供更细致的控制。
- GROUP BY子句必须出现在WHERE子句之后,ORDER BY子句之前。
4.1 过滤分组
为WHERE过滤指定的是行而不是分组,如果要对分组进行过滤,需要使用HAVING子句。
mysql> SELECT cust_id, COUNT(*) AS orders
-> FROM orders
-> GROUP BY cust_id
-> HAVING COUNT(*)>=2;
+---------+--------+
| cust_id | orders |
+---------+--------+
| 10001 | 2 |
+---------+--------+
1 row in set (0.24 sec)
HAVING也可以和WHERE共用:
mysql> SELECT vend_id,COUNT(*) AS num_prods
-> FROM products
-> WHERE prod_price>=10
-> GROUP BY vend_id
-> HAVING COUNT(*)>=2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| 1003 | 4 |
| 1005 | 2 |
+---------+-----------+
2 rows in set (0.24 sec)
4.3 SELECT子句顺序
目前已经介绍了WHERE, GROUP BY, HAVING, ORDER BY, LIMIT等子句,这些字句都可以共用,但顺序需要注意。
子句 | 作用 |
---|---|
SELECT | 选择一些列或表达式 |
FROM | 要检索的表 |
WHERE | 行级过滤 |
GROUP BY | 分组说明 |
HAVING | 组级过滤 |
ORDER BY | 排序 |
LIMIT | 输出的行数 |
5. 子查询
所谓子查询就是在WHERE中再嵌套WHERE,用IN连接
mysql> SELECT cust_id FROM orders
-> WHERE order_num IN
-> (SELECT order_num FROM orderitems
-> WHERE prod_id = 'TNT2');
+---------+
| cust_id |
+---------+
| 10001 |
| 10004 |
+---------+
2 rows in set (0.56 sec)
当然也可以使用计算字段来进行过滤查询。下面这个例子中查询了两个表:customers和orders,将orders表中查询到的各个客户的订单数量,汇总。
mysql> SELECT cust_name, cust_state,
-> (SELECT COUNT(*) FROM orders
-> WHERE orders.cust_id = customers.cust_id)
-> AS orders
-> FROM customers ORDER BY cust_name;
+----------------+------------+--------+
| cust_name | cust_state | orders |
+----------------+------------+--------+
| Coyote Inc. | MI | 2 |
| E Fudd | IL | 1 |
| Mouse House | OH | 0 |
| Wascals | IN | 1 |
| Yosemite Place | AZ | 1 |
+----------------+------------+--------+
5 rows in set (0.25 sec)
6. 组合查询
前面提到WHERE可以使用OR组合查询条件,这里再提供另一种查询方法UNION
mysql> SELECT vend_id, prod_id, prod_price
-> FROM products
-> WHERE prod_price<=5
-> UNION
-> SELECT vend_id, prod_id, prod_price
-> FROM products
-> WHERE vend_id IN(1001,1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1003 | FC | 2.50 |
| 1002 | FU1 | 3.42 |
| 1003 | SLING | 4.49 |
| 1003 | TNT1 | 2.50 |
| 1001 | ANV01 | 5.99 |
| 1001 | ANV02 | 9.99 |
| 1001 | ANV03 | 14.99 |
| 1002 | OL1 | 8.99 |
+---------+---------+------------+
8 rows in set (0.24 sec)
他等价于WHERE和OR的组合:
mysql> SELECT vend_id, prod_id, prod_price
-> FROM products
-> WHERE prod_price<=5 OR vend_id IN(1001,1002);
+---------+---------+------------+
| vend_id | prod_id | prod_price |
+---------+---------+------------+
| 1001 | ANV01 | 5.99 |
| 1001 | ANV02 | 9.99 |
| 1001 | ANV03 | 14.99 |
| 1003 | FC | 2.50 |
| 1002 | FU1 | 3.42 |
| 1002 | OL1 | 8.99 |
| 1003 | SLING | 4.49 |
| 1003 | TNT1 | 2.50 |
+---------+---------+------------+
8 rows in set (0.24 sec)