第七章 查詢資料
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 分組查詢
- 建立分組
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)
- 使用HAVING過濾分組
HAVING 在資料分組之後進行過濾來分組。 - 在GROUP BY子句中使用WITH ROOLUP
使用WITH ROLLUP關鍵字之後,在所有查詢出的分組記錄之後增加一條記錄,該記錄計算查詢出的所有記錄的總和。 - 多欄位分組
即GROUP BY 後面接需要的分組欄位。 - 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 綜合案例
- 建立資料表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)
- 將指定記錄分別插入兩個表中
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
- 在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)
- 在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)
- 在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)
- 在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)
- 在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)
- 查詢員工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)
- 使用連線查詢,查詢所有員工的部門和部門資訊
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)
- 在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)
- 在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)
- 在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)
- 在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)
- 在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)
- 在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)
- 在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)