SELECT

子句说明

子句说明是否必须使用
SELECT要返回的列或表达式
FROM从中检索数据的表仅在从表选择数据时使用
WHERE行级过滤
GROUP BY分组说明仅在按组计算聚集时使用
HAVING组级过滤
ORDER BY输出排序顺序
LIMIT要检索的行数

指从表的一个或多个数据列。

列选择

-- 单列
SELECT 
  prod_name
FROM products

-- 多列
SELECT 
  prod_id,
  prod_name,
  prod_price
FROM products

-- 全部
SELECT * FROM products

限制结果

-- 直接在列上限制
SELECT 
  DISTINCT vend_id
FROM products

-- 限制
SELECT 
  prod_name
FROM products
LIMIT 5

-- 偏移
SELECT 
  prod_name
FROM products
LIMIT 5, 5

排序

排序的概念比较简单,需要注意的是一般会将其放在后面执行。

-- 指定排序
SELECT 
  prod_name
FROM products
ORDER BY prod_name

-- 二次排序
SELECT 
  prod_id,
  prod_name,
  prod_price
FROM products
ORDER BY prod_price, prod_name

-- 指定顺序规则
-- 配合上 LIMIT 达到查询最大最小
SELECT 
  prod_id,
  prod_name,
  prod_price
FROM products
ORDER BY prod_price DESC, prod_name

过滤

感觉与日常要写的 filter 方法一致。

简单 WHERE

-- 简单
SELECT 
  prod_name,
  prod_price
FROM products
WHERE prod_price = 2.5

-- 范围
SELECT 
  prod_name,
  prod_price
FROM products
WHERE prod_price BETWEEN 2 AND 5

-- NULL
SELECT 
  cust_id,
  cust_name
FROM customers
WHERE cust_email IS NULL

组合语句

注意 AND 和 OR 同时使用时 AND 计算优先级更高,在任何多种操作符存在时都使用 () 明确区分,避免出现问题。

SELECT 
  vend_id,
  prod_id,
  prod_name,
  prod_price
FROM products
WHERE vend_id = 1002 OR vend_id = 1003 AND prod_price <= 5

范围表示

IN 操作符可表示条件范围,可利用 IN WHERE 子句完成一些麻烦的手写行为。

SELECT 
  vend_id,
  prod_id,
  prod_name,
  prod_price
FROM products
WHERE vend_id IN (1002, 1003)
ORDER BY prod_price

-- NOT
SELECT 
  vend_id,
  prod_id,
  prod_name,
  prod_price
FROM products
WHERE vend_id NOT IN (1002, 1003)
ORDER BY prod_price

-- 子查询
SELECT 
  cust_name,
  cust_contact
FROM customers
WHERE cust_id IN (
  SELECT
    cust_id
  FROM orders
  WHERE order_num IN (
    SELECT 
      order_num
    FROM orderitems
    WHERE prod_id = 'TNT2'
  )
)

通配符

前面的过滤很常见,但更实用的还看通配符。

-- % 表示任何字符出现任意次数
SELECT 
  prod_id,
  prod_name
FROM products
WHERE prod_name LIKE "%an%"

-- 匹配中间
SELECT 
  prod_id,
  prod_name
FROM products
WHERE prod_name LIKE "s%e"

-- _ 表示任何字符出现一次
SELECT 
  prod_id,
  prod_name
FROM products
WHERE prod_name LIKE "_et%"

正则表达式

无论啥语言都逃不过正则表达式的魔爪,幸运的是它们的规则、关键字基本相通,减少了学习成本。

SELECT 
  prod_id,
  prod_name
FROM products
WHERE prod_name REGEXP '[1-9] Ton'

-- MySQL 解释一次、正则表达式库再解释一次
SELECT 
  prod_id,
  prod_name
FROM products
WHERE prod_name REGEXP '\\d{4}'

对特殊格式的处理

例如日期格式,当仅想对比到日时:

SELECT 
  cust_id,
  order_num,
  order_date
FROM orders
WHERE date(order_date) = '2005-09-01'

更多内置的方法可参考open in new window

计算字段

很多时候是由计算返回的结果。别名 alias 可简写为 AS,甚至还可忽略。

SELECT 
  vend_id,
  concat(vend_name, '(',vend_country, ')') vend_title
FROM vendors
ORDER BY vend_name

-- 算术运算
SELECT 
  prod_id,
  quantity,
  item_price,
  quantity * item_price AS total_price
FROM orderitems
WHERE order_num = 20005

-- 子查询
SELECT
  cust_name,
  cust_state,
  (
    SELECT 
      count(*)
    FROM orders
    WHERE orders.cust_id = c.cust_id
  ) AS orders
FROM customers c
ORDER BY cust_name

分组

如果对 count(*) 存在困惑的话,配合上分组就好理解了。

SELECT 
  vend_id,
  count(*) AS num_prods
FROM products
GROUP BY vend_id

需注意配合分组使用的是 HAVING 而非 WHERE,一种理解是 WHERE 在数据分组前进行过滤,HAVING 在数据分组后进行过滤,到底是怎么回事得看 MySQL 的源码了。

SELECT 
  vend_id,
  count(*) AS num_prods
FROM products
GROUP BY vend_id
HAVING count(*) > 2