1. 程式人生 > >第七章 查詢資料

第七章 查詢資料

7.1 基本查詢語句
使用SELECT語句。其基本格式:

SELECT 
{*|<欄位列表>}
[
FROM <表1>,<表2>...
[WHERE <表示式>
HAVING____
GROUP BY__
ORDER BY__
LIMIT__
]
SELECT[欄位1,欄位2,...]
FROM[表或檢視]
WHERE[查詢條件]

WHERE子句是可選項,如果選擇該選項,將限定查詢行必須滿足的查詢條件。
下面使用一個例子說明如何使用SELECT從單個表中獲取資料。
首先定義資料表,輸入如下語句:

mysql> CREATE TABLE fruits(
    -> f_id char(10) NOT NULL,
    -> s_id INT NOT NULL,
    -> f_name char(255) NOT NULL,
    -> f_price decimal(8,2) NOT NULL,
    -> PRIMARY KEY(f_id)
    -> );
Query OK, 0 rows affected (0.36 sec)

插入資料:

mysql> INSERT INTO fruits(f_id,s_id,f_name,f_price)
    -> VALUES('a1',101,'apple',5.2),
    -> ('b1',101,'blackberry',10.2),
    -> ('bs1',102,'orange',11.2),
    -> ('bs2',105,'melon',8.2),
    -> ('t1',102,'banana',10.3),
    -> ('t2',102,'grape',5.3),
    -> ('o2',103,'coconut',9.2),
    -> ('c0',101,'cherry',3.2),
    -> ('a2',103,'apricot',2.2),
    -> ('l2',104,'lemon',6.4),
    -> ('b2',104,'berry',7.6),
    -> ('m1',106,'mango',15.6),
    -> ('m2',105,'xbabay',2.6),
    -> ('t4',107,'xbababa',3.6),
    -> ('m3',105,'xxtt',11.6),
    -> ('b5',107,'xxxx',3.6);
Query OK, 16 rows affected (0.09 sec)
Records: 16  Duplicates: 0  Warnings: 0

使用SELECT語句查詢f_id欄位:

mysql> SELECT f_id FROM fruits;
+------+
| f_id |
+------+
| a1   |
| a2   |
| b1   |
| b2   |
| b5   |
| bs1  |
| bs2  |
| c0   |
| l2   |
| m1   |
| m2   |
| m3   |
| o2   |
| t1   |
| t2   |
| t4   |
+------+
16 rows in set (0.13 sec)

7.2 單表查詢

SELECT * FROM db;比列出所有屬性名效率低,因為*有一個轉換的過程。

在MySQL中,可通過SELECT __ FROM __ WHERE__來查詢指定記錄。
WHERE後面的操作符有:
IN:用來查詢滿足指定範圍內的條件的記錄;
BETWEEN AND:用來查詢某個範圍內的值;
LIKE:使用萬用字元進行匹配查詢;
(萬用字元%用於匹配在指定位置的任意數目的字元。b%:b開頭;%g%:包含g;b%y:b開頭,y結尾。)
(_萬用字元,只能匹配任意單個字元,即指定個數)
AND:限定只有滿足所有查詢條件的記錄才會被返回,AND可以連線兩個甚至兩個以上的查詢條件。
OR:只需滿足其中一個條件即可返回。(注意:AND的優先順序大於OR)

7.2.10查詢結果不重複
DISTINCT:使查詢結果不重複

mysql> SELECT DISTINCT Id,name FROM worker;
+----+--------+
| Id | name   |
+----+--------+
|  1 | jimy   |
|  2 | Tom    |
|  3 | Keiven |
|  4 | Michal |
|  5 | Nick   |
+----+--------+
5 rows in set (0.00 sec)

7.2.11 對查詢結果排序

  • 單列排序

mysql> SELECT name FROM worker ORDER BY name;
+--------+
| name   |
+--------+
| jimy   |
| Keiven |
| Michal |
| Nick   |
| Tom    |
+--------+
5 rows in set (0.10 sec)
  • 多列排序
mysql> SELECT name,Id FROM worker ORDER BY name,Id;
+--------+----+
| name   | Id |
+--------+----+
| jimy   |  1 |
| Keiven |  3 |
| Michal |  4 |
| Nick   |  5 |
| Tom    |  2 |
+--------+----+
5 rows in set (0.00 sec)

注:在對多列進行排序的時候,首先排序的第一列必須有相同的列值,才會對第二列進行排序。如果第一列所有值都是唯一的,將不再對第二列進行排序。

  • 指定排序方向
    排序預設為升序:ASC;可以自己指定升降序,ORDER BY__ ASC/DESC。
mysql> SELECT Id FROM worker ORDER BY Id DESC;
+----+
| Id |
+----+
|  5 |
|  4 |
|  3 |
|  2 |
|  1 |
+----+
5 rows in set (0.11 sec)

7.2.12 分組查詢

  1. 建立分組
    GROUP關鍵字通常和集合函式一起使用,如:MAX()、MIN()、COUNT()、SUM()、AVG()。
mysql> SELECT Id,COUNT(*) AS Total FROM worker GROUP BY Id;
+----+-------+
| Id | Total |
+----+-------+
|  1 |     1 |
|  2 |     1 |
|  3 |     1 |
|  4 |     1 |
|  5 |     1 |
+----+-------+
5 rows in set (0.00 sec)
  1. 使用HAVING過濾分組
    HAVING 在資料分組之後進行過濾來分組。
  2. 在GROUP BY子句中使用WITH ROOLUP
    使用WITH ROLLUP關鍵字之後,在所有查詢出的分組記錄之後增加一條記錄,該記錄計算查詢出的所有記錄的總和。
  3. 多欄位分組
    即GROUP BY 後面接需要的分組欄位。
  4. GROUP BU和ORDER BY 一起使用
    注:使用ROOLUP時,不能同時使用ORDER BY子句進行結果排序。

7.4 內連線查詢
內連線(INNER JOIN)使用比較運算子進行表間某些列資料的比較操作,並列出這些表中與連線相匹配的資料行,組合成新的記錄。p212.

7.7 為表和欄位取別名
使用AS。

7.8 使用正則表示式查詢
REGEXP關鍵字指定正則表示式的字元匹配模式。
^:匹配文字的開始字元
$:匹配文字的結束字元
.:匹配任何單個字元,如b.t:bit、bat等
*:匹配零個或多個在它前面的字元
+:匹配前面的字元一次或多次,如:ba+:b開頭後面緊跟至少一個a
<字串>:匹配包含指定的字串的文字
[字符集]:匹配字符集中的任意一個字元
[^]:匹配不在括號中的任何字元
字串{n,}:匹配前面的字串至少n次
字串{n,m}:匹配前面的字串至少n次,至多m次

7.9 綜合案例

  1. 建立資料表employee和dept
mysql> CREATE TABLE dept(
    -> d_no INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    -> d_name VARCHAR(50),
    -> d_location VARCHAR(100)
    -> );
Query OK, 0 rows affected (0.37 sec)
mysql> CREATE TABLE employee(
    -> e_no INT NOT NULL PRIMARY KEY,
    -> e_name VARCHAR(100) NOT NULL,
    -> e_gender CHAR(2) NOT NULL,
    -> dept_no INT NOT NULL,
    -> e_job VARCHAR(100) NOT NULL,
    -> e_salary SMALLINT NOT NULL,
    -> hireDate DATE,
    -> CONSTRAINT dno_fk FOREIGN KEY(dept_no)
    -> REFERENCES dept(d_no)
    -> );
Query OK, 0 rows affected (0.35 sec)
  1. 將指定記錄分別插入兩個表中
mysql> INSERT INTO dept
    -> VALUES (10,'ACCOUNTING','ShangHai'),
    -> (20,'RESEARCH','BeiJing'),
    -> (30,'SALES','ShenZhen'),
    -> (40,'OPERATIONS','FuJian');
Query OK, 4 rows affected (0.06 sec)
Records: 4  Duplicates: 0  Warnings: 0
mysql> INSERT INTO employee
    -> VALUES(1001,'SMITH','m',20,'CLERK',800,'2005-11-12'),
    -> (1002,'ALLEN','f',30,'SALESMAN',1600,'2001-05-12'),
    -> (1003,'WARD','f',30,'SALESMAN',1250,'2001-05-12'),
    -> (1004,'JONES','m',20,'MANAGER',2975,'1998-05-18'),
    -> (1005,'MARTIN','m',30,'SALSMAN',1250,'2001-06-12'),
    -> (1006,'BLAKE','f',30,'MANAGER',2850,'1997-02-15'),
    -> (1007,'CLARK','m',10,'MANAGER',2450,'2002-09-12'),
    -> (1008,'SCOTT','m',20,'ANALYST',3000,'2003-05-12'),
    -> (1009,'KING','f',10,'PRESIDENT',5000,'1995-01-01'),
    -> (1010,'TURNER','f',30,'SALESMAN',1500,'1997-10-12'),
    -> (1011,'ADAMS','m',20,'CLERK',1100,'1999-10-05'),
    -> (1012,'JAMES','m',30,'CLERK',950,'2008-06-15');
Query OK, 12 rows affected (0.46 sec)
Records: 12  Duplicates: 0  Warnings: 0
  1. 在employee表中,查詢有記錄的e_no、e_name和e_salary欄位
mysql> SELECT e_no,e_name,e_salary FROM employee;
+------+--------+----------+
| e_no | e_name | e_salary |
+------+--------+----------+
| 1001 | SMITH  |      800 |
| 1002 | ALLEN  |     1600 |
| 1003 | WARD   |     1250 |
| 1004 | JONES  |     2975 |
| 1005 | MARTIN |     1250 |
| 1006 | BLAKE  |     2850 |
| 1007 | CLARK  |     2450 |
| 1008 | SCOTT  |     3000 |
| 1009 | KING   |     5000 |
| 1010 | TURNER |     1500 |
| 1011 | ADAMS  |     1100 |
| 1012 | JAMES  |      950 |
+------+--------+----------+
12 rows in set (0.00 sec)
  1. 在employee表中,查詢dept_no=10和20的所有記錄
mysql> SELECT * FROM employee WHERE dept_no IN (10,20);
+------+--------+----------+---------+-----------+----------+------------+
| e_no | e_name | e_gender | dept_no | e_job     | e_salary | hireDate   |
+------+--------+----------+---------+-----------+----------+------------+
| 1001 | SMITH  | m        |      20 | CLERK     |      800 | 2005-11-12 |
| 1004 | JONES  | m        |      20 | MANAGER   |     2975 | 1998-05-18 |
| 1007 | CLARK  | m        |      10 | MANAGER   |     2450 | 2002-09-12 |
| 1008 | SCOTT  | m        |      20 | ANALYST   |     3000 | 2003-05-12 |
| 1009 | KING   | f        |      10 | PRESIDENT |     5000 | 1995-01-01 |
| 1011 | ADAMS  | m        |      20 | CLERK     |     1100 | 1999-10-05 |
+------+--------+----------+---------+-----------+----------+------------+
6 rows in set (0.01 sec)
  1. 在employee表中,查詢工資範圍在800~2500之間的員工資訊
mysql> SELECT * FROM employee WHERE e_salary BETWEEN 800 AND 2500;
+------+--------+----------+---------+----------+----------+------------+
| e_no | e_name | e_gender | dept_no | e_job    | e_salary | hireDate   |
+------+--------+----------+---------+----------+----------+------------+
| 1001 | SMITH  | m        |      20 | CLERK    |      800 | 2005-11-12 |
| 1002 | ALLEN  | f        |      30 | SALESMAN |     1600 | 2001-05-12 |
| 1003 | WARD   | f        |      30 | SALESMAN |     1250 | 2001-05-12 |
| 1005 | MARTIN | m        |      30 | SALSMAN  |     1250 | 2001-06-12 |
| 1007 | CLARK  | m        |      10 | MANAGER  |     2450 | 2002-09-12 |
| 1010 | TURNER | f        |      30 | SALESMAN |     1500 | 1997-10-12 |
| 1011 | ADAMS  | m        |      20 | CLERK    |     1100 | 1999-10-05 |
| 1012 | JAMES  | m        |      30 | CLERK    |      950 | 2008-06-15 |
+------+--------+----------+---------+----------+----------+------------+
8 rows in set (0.00 sec)

  1. 在employee表中,查詢部門編號為20的部門中的員工資訊
mysql> SELECT * FROM employee WHERE dept_no=20;
+------+--------+----------+---------+---------+----------+------------+
| e_no | e_name | e_gender | dept_no | e_job   | e_salary | hireDate   |
+------+--------+----------+---------+---------+----------+------------+
| 1001 | SMITH  | m        |      20 | CLERK   |      800 | 2005-11-12 |
| 1004 | JONES  | m        |      20 | MANAGER |     2975 | 1998-05-18 |
| 1008 | SCOTT  | m        |      20 | ANALYST |     3000 | 2003-05-12 |
| 1011 | ADAMS  | m        |      20 | CLERK   |     1100 | 1999-10-05 |
+------+--------+----------+---------+---------+----------+------------+
4 rows in set (0.00 sec)
  1. 在employee表中,查詢每個部門的最高工資的員工資訊
mysql> SELECT dept_no,MAX(e_salary) FROM employee GROUP BY dept_no;
+---------+---------------+
| dept_no | MAX(e_salary) |
+---------+---------------+
|      10 |          5000 |
|      20 |          3000 |
|      30 |          2850 |
+---------+---------------+
3 rows in set (0.00 sec)

  1. 查詢員工BLAKE所在部門和部門所在地
mysql> SELECT d_no,d_location FROM dept WHERE d_no
    -> =(SELECT dept_no FROM employee WHERE e_name='BLAKE');
+------+------------+
| d_no | d_location |
+------+------------+
|   30 | ShenZhen   |
+------+------------+
1 row in set (0.00 sec)
  1. 使用連線查詢,查詢所有員工的部門和部門資訊
mysql> SELECT e_no,e_name,dept_no,d_name,d_location
    -> FROM employee,dept WHERE dept.d_no=employee.dept_no;
+------+--------+---------+------------+------------+
| e_no | e_name | dept_no | d_name     | d_location |
+------+--------+---------+------------+------------+
| 1007 | CLARK  |      10 | ACCOUNTING | ShangHai   |
| 1009 | KING   |      10 | ACCOUNTING | ShangHai   |
| 1001 | SMITH  |      20 | RESEARCH   | BeiJing    |
| 1004 | JONES  |      20 | RESEARCH   | BeiJing    |
| 1008 | SCOTT  |      20 | RESEARCH   | BeiJing    |
| 1011 | ADAMS  |      20 | RESEARCH   | BeiJing    |
| 1002 | ALLEN  |      30 | SALES      | ShenZhen   |
| 1003 | WARD   |      30 | SALES      | ShenZhen   |
| 1005 | MARTIN |      30 | SALES      | ShenZhen   |
| 1006 | BLAKE  |      30 | SALES      | ShenZhen   |
| 1010 | TURNER |      30 | SALES      | ShenZhen   |
| 1012 | JAMES  |      30 | SALES      | ShenZhen   |
+------+--------+---------+------------+------------+
12 rows in set (0.00 sec)
  1. 在employee表中,計算每個部門各有多少名員工
mysql> SELECT dept_no,COUNT(*) FROM employee GROUP BY dept_no;
+---------+----------+
| dept_no | COUNT(*) |
+---------+----------+
|      10 |        2 |
|      20 |        4 |
|      30 |        6 |
+---------+----------+
3 rows in set (0.00 sec)
  1. 在employee表中,計算不同型別職工的總工資數
mysql> SELECT e_job,SUM(e_salary) FROM employee GROUP BY e_job;
+-----------+---------------+
| e_job     | SUM(e_salary) |
+-----------+---------------+
| ANALYST   |          3000 |
| CLERK     |          2850 |
| MANAGER   |          8275 |
| PRESIDENT |          5000 |
| SALESMAN  |          4350 |
| SALSMAN   |          1250 |
+-----------+---------------+
6 rows in set (0.00 sec)
  1. 在employee表中,計算不同部門的平均工資
mysql> SELECT dept_no,AVG(e_salary) FROM employee GROUP BY dept_no;
+---------+---------------+
| dept_no | AVG(e_salary) |
+---------+---------------+
|      10 |     3725.0000 |
|      20 |     1968.7500 |
|      30 |     1566.6667 |
+---------+---------------+
3 rows in set (0.00 sec)
  1. 在employee表中,查詢工資低於1500的員工資訊
mysql> SELECT * FROM employee WHERE e_salary<1500;
+------+--------+----------+---------+----------+----------+------------+
| e_no | e_name | e_gender | dept_no | e_job    | e_salary | hireDate   |
+------+--------+----------+---------+----------+----------+------------+
| 1001 | SMITH  | m        |      20 | CLERK    |      800 | 2005-11-12 |
| 1003 | WARD   | f        |      30 | SALESMAN |     1250 | 2001-05-12 |
| 1005 | MARTIN | m        |      30 | SALSMAN  |     1250 | 2001-06-12 |
| 1011 | ADAMS  | m        |      20 | CLERK    |     1100 | 1999-10-05 |
| 1012 | JAMES  | m        |      30 | CLERK    |      950 | 2008-06-15 |
+------+--------+----------+---------+----------+----------+------------+
5 rows in set (0.00 sec)
  1. 在employee表中,將查詢記錄先按部門編號由高到低排列,再按員工工資由高到低排列
mysql> SELECT e_name,dept_no,e_salary FROM employee
    -> ORDER BY dept_no DESC,e_salary DESC;
+--------+---------+----------+
| e_name | dept_no | e_salary |
+--------+---------+----------+
| BLAKE  |      30 |     2850 |
| ALLEN  |      30 |     1600 |
| TURNER |      30 |     1500 |
| WARD   |      30 |     1250 |
| MARTIN |      30 |     1250 |
| JAMES  |      30 |      950 |
| SCOTT  |      20 |     3000 |
| JONES  |      20 |     2975 |
| ADAMS  |      20 |     1100 |
| SMITH  |      20 |      800 |
| KING   |      10 |     5000 |
| CLARK  |      10 |     2450 |
+--------+---------+----------+
12 rows in set (0.00 sec)
  1. 在employee表中,查詢員工姓名以字母‘A’或‘S’開頭的員工資訊
mysql> SELECT * FROM employee WHERE e_name REGEXP'^[AS]';
+------+--------+----------+---------+----------+----------+------------+
| e_no | e_name | e_gender | dept_no | e_job    | e_salary | hireDate   |
+------+--------+----------+---------+----------+----------+------------+
| 1001 | SMITH  | m        |      20 | CLERK    |      800 | 2005-11-12 |
| 1002 | ALLEN  | f        |      30 | SALESMAN |     1600 | 2001-05-12 |
| 1008 | SCOTT  | m        |      20 | ANALYST  |     3000 | 2003-05-12 |
| 1011 | ADAMS  | m        |      20 | CLERK    |     1100 | 1999-10-05 |
+------+--------+----------+---------+----------+----------+------------+
4 rows in set (0.10 sec)

  1. 在employee表中,查詢到目前為止,工齡大於等於十年的員工資訊
mysql> SELECT * FROM employee WHERE YEAR(CURDATE())-YEAR(hireDate)>=10;
+------+--------+----------+---------+-----------+----------+------------+
| e_no | e_name | e_gender | dept_no | e_job     | e_salary | hireDate   |
+------+--------+----------+---------+-----------+----------+------------+
| 1001 | SMITH  | m        |      20 | CLERK     |      800 | 2005-11-12 |
| 1002 | ALLEN  | f        |      30 | SALESMAN  |     1600 | 2001-05-12 |
| 1003 | WARD   | f        |      30 | SALESMAN  |     1250 | 2001-05-12 |
| 1004 | JONES  | m        |      20 | MANAGER   |     2975 | 1998-05-18 |
| 1005 | MARTIN | m        |      30 | SALSMAN   |     1250 | 2001-06-12 |
| 1006 | BLAKE  | f        |      30 | MANAGER   |     2850 | 1997-02-15 |
| 1007 | CLARK  | m        |      10 | MANAGER   |     2450 | 2002-09-12 |
| 1008 | SCOTT  | m        |      20 | ANALYST   |     3000 | 2003-05-12 |
| 1009 | KING   | f        |      10 | PRESIDENT |     5000 | 1995-01-01 |
| 1010 | TURNER | f        |      30 | SALESMAN  |     1500 | 1997-10-12 |
| 1011 | ADAMS  | m        |      20 | CLERK     |     1100 | 1999-10-05 |
| 1012 | JAMES  | m        |      30 | CLERK     |      950 | 2008-06-15 |
+------+--------+----------+---------+-----------+----------+------------+
12 rows in set (0.17 sec)