总结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)