MySQL快速入門09----查詢(1)


select 語法:

select select_expr [from tbl_name] [where] [group by] [having] [order by] [limit]
select [查詢選項] [查詢表達式(字段表達式)] [from 子句] [where 子句] [group by 子句] [having 子句] [order by 子句] [limit 子句]
注意:select 子句可以不出現,如果出現則必須按照順序出現!


創建新表teacher_class:

mysql> create table teacher_class (
    -> id int primary key auto_increment,
    -> t_name varchar(10),
    -> gender enum('female', 'male', 'secret'),
    -> c_name char(7),
    -> room char(3),
    -> days tinyint unsigned,
    -> begin_date date,
    -> end_date date
    -> ) character set utf8;
Query OK, 0 rows affected (0.06 sec)


向新表中插入數據:

insert into teacher_class values
(null, '韓信', 'male', 'php0115', '207', 21, '2013-01-15', '2013-02-20'),
(null, '韓信', 'male', 'php0228', '106', 18, '2013-02-28', '2013-03-30'),
(null, '韓信', 'male', 'php0331', '102', 24, '2013-03-31', '2013-05-05'),
(null, '李白', 'male', 'php0115', '207', 20, '2013-02-22', '2013-03-25'),
(null, '李白', 'male', 'php0228', '204', 21, '2013-03-31', '2013-04-29'),
(null, '韓非', 'secret', 'php0115', '207', 15, '2013-03-27', '2013-04-18');

數據展示:

mysql> select * from teacher_class;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  1 | 韓信       | male   | php0115 | 207  |   21 | 2013-01-15 | 2013-02-20 |
|  2 | 韓信       | male   | php0228 | 106  |   18 | 2013-02-28 | 2013-03-30 |
|  3 | 韓信       | male   | php0331 | 102  |   24 | 2013-03-31 | 2013-05-05 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  5 | 李白       | male   | php0228 | 204  |   21 | 2013-03-31 | 2013-04-29 |
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
+----+--------+--------+---------+------+------+------------+------------+
6 rows in set (0.02 sec)


表達式:


查詢列可以是一個列名,表達式都可以。每個列之間使用逗號分割。

字段也是可以參與運算的,數據是保存在字段內的,因此可以將字段當作變量來看待。

AS Alias可以爲每一個列指明一個別名,可用於group by ,having 或 order by 子句。

其中AS是可以選用的,但是建議使用。不使用可能會出現 field1 field2沒有寫逗號分割,導致將第二個認爲是第一個的別名。


字段(變量),函數返回值:
mysql> select 10+20;
+-------+
| 10+20 |
+-------+
|    30 |
+-------+
1 row in set (0.00 sec)

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2016-08-05 20:00:20 |
+---------------------+
1 row in set (0.02 sec)

mysql> select now(), unix_timestamp();
+---------------------+------------------+
| now()               | unix_timestamp() |
+---------------------+------------------+
| 2016-08-05 20:03:31 |       1470398611 |
+---------------------+------------------+
1 row in set (0.03 sec)

mysql> select now() time, unix_timestamp() 時間戳;
+---------------------+------------+
| time                | 時間戳          |
+---------------------+------------+
| 2016-08-05 20:04:09 | 1470398649 |
+---------------------+------------+
1 row in set (0.00 sec)


列子句:


如果是從表中獲得數據,那麼字段,就是變量,可以參與任何運算(concat函數將字符串連接起來):
mysql> select id, concat(t_name, '-', gender), c_name from teacher_class;
+----+-----------------------------+---------+
| id | concat(t_name, '-', gender) | c_name  |
+----+-----------------------------+---------+
|  1 | 韓信-male                       | php0115 |
|  2 | 韓信-male                       | php0228 |
|  3 | 韓信-male                       | php0331 |
|  4 | 李白-male                       | php0115 |
|  5 | 李白-male                       | php0228 |
|  6 | 韓非-secret                     | php0115 |
+----+-----------------------------+---------+
6 rows in set (0.00 sec)


別名as


常一個表達式,形式不夠良好,不容易讀取;起一個 可以容易讀取的別名即可:使用 關鍵字 AS
標識符 [as] 別名

注意:as可以省略,一個字段後面的標識符,就是當前的別名

建議不要忽略別名關鍵字as!

mysql> select id as 標號, t_name 姓名 from teacher_class;
+------+------+
| 標號     | 姓名     |
+------+------+
|    1 | 韓信     |
|    2 | 韓信     |
|    3 | 韓信     |
|    4 | 李白     |
|    5 | 李白     |
|    6 | 韓非     |
+------+------+
6 rows in set (0.00 sec)
注意:當字符串中出現空格的時候需要使用單引號!

From子句


表示查詢的目標數據源,通常情況下是表名(也支持別名)。

mysql> select id, t_name from teacher_class 表;
+----+--------+
| id | t_name |
+----+--------+
|  1 | 韓信       |
|  2 | 韓信       |
|  3 | 韓信       |
|  4 | 李白       |
|  5 | 李白       |
|  6 | 韓非       |
+----+--------+
6 rows in set (0.00 sec)

表名也是一個列表:如果沒有任何條件的兩個表名,會得到 表1乘表2內的所有數據。交叉連接,笛卡爾積

如teacher_class中有六行數據,auin_1中有八行數據,那麼接下來就有48行數據:
mysql> select * from teacher_class,auin_1;
48 rows in set (0.00 sec)
中間表中的數據沒有列出。

表名可以是tbl_name或者db_name.tbl_name。

表可以是一個或者多個,使用逗號分割(參考多表操作)

虛擬表dual


可以不存在表名,此時可以使用一個dual作爲僞表名,來保證sql語法的兼容性(有些服務器要求必須有表名)。

mysql> select now() from dual;
+---------------------+
| now()               |
+---------------------+
| 2016-08-05 20:16:56 |
+---------------------+
1 row in set (0.00 sec)

不建表而進行相關函數的查詢工作。

From 可以省略,但是有些服務器是不允許省略。
mysql支持使用dual作爲虛擬表。




運算符




常用的運算符:
等於:=
不等於:<> !=
小於,小於等於,大於,大於等於:< <= > >=
模糊匹配:like ‘pattern’ ,通配符_表示單個字符%表示任意字符的任意組合\%轉義%. \_轉義_
布爾判斷:is 布爾值|is not 布爾值。布爾值可以爲 true,false
Null值判斷:is null | Is not null。還可以使用 ISNULL()
NULL-Safe等於:與=相同,不過支持null運算。<=> null <=> null 1 null <=> other 0
範圍:expr BETWEEN min AND max 。閉區間(大於等於,小於等於)。  (min <= expr AND expr <= max)
不在某個區間:expr NOT BETWEEN min AND max 。NOT(expr BETWEEN min AND max)
在集合內:expr IN (value,...)
不在集合內:expr NOT IN (value,...)
返回指定位置:INTERVAL(N,N1,N2,N3,...)
返回最小值:LEAST(value1,value2,...)
返回最大值:GREATEST(value1,value2,...)
找到第一個非零的值:COALESCE(value,...)

邏輯運算符:
非:not !,非null 爲null。
與:and &&,有0就是0,都是非零爲1,存在null與非零則爲null。
或:or || , null||null=null null||1=1 null||0=null
異或: xor ,有null,就是null。

優先級
運算符的組合,也支持優先級,可以使用小括號完成定義優先級。

mysql> select null is not null, null is null;
+------------------+--------------+
| null is not null | null is null |
+------------------+--------------+
|                0 |            1 |
+------------------+--------------+
1 row in set (0.00 sec)
判斷null值用is null或者is not null。

<=> 功能與 =一致,特別的功能在於 可以比較null值。

mysql> select null <=> null, 10 <=> null;
+---------------+-------------+
| null <=> null | 10 <=> null |
+---------------+-------------+
|             1 |           0 |
+---------------+-------------+
1 row in set (0.02 sec)

between A and B,取A和B之間的數值,包含A和B
mysql> select * from teacher_class where days between 15 and 20;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  2 | 韓信       | male   | php0228 | 106  |   18 | 2013-02-28 | 2013-03-30 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
+----+--------+--------+---------+------+------+------------+------------+
3 rows in set (0.00 sec)

另外一種表示方法:
mysql> select * from teacher_class where days<=20 and days>=15;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  2 | 韓信       | male   | php0228 | 106  |   18 | 2013-02-28 | 2013-03-30 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
+----+--------+--------+---------+------+------+------------+------------+
3 rows in set (0.00 sec)

另外一種方式方法:
mysql> select * from teacher_class where days<=20 && days>=15;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  2 | 韓信       | male   | php0228 | 106  |   18 | 2013-02-28 | 2013-03-30 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
+----+--------+--------+---------+------+------+------------+------------+
3 rows in set (0.00 sec)


in代表在集合之內,取出天數在15、18、20的表的信息:
mysql> select * from teacher_class where days in (15, 18,20);
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  2 | 韓信       | male   | php0228 | 106  |   18 | 2013-02-28 | 2013-03-30 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
+----+--------+--------+---------+------+------+------------+------------+
3 rows in set (0.00 sec)

interval獲取一個元素的索引:
Interval(值, 元素1, 元素2, 元素N);
依次判斷值,與元素之間的大小關係,如果值小於元素1,則返回0;
如果值小於元素2 則返回1,依次類推。
mysql> select t_name, days, interval(days, 10, 20, 30) from teacher_class where interval(days,10,20,30)=1;
+--------+------+----------------------------+
| t_name | days | interval(days, 10, 20, 30) |
+--------+------+----------------------------+
| 韓信       |   18 |                          1 |
| 韓非       |   15 |                          1 |
+--------+------+----------------------------+
上述代碼顯示出days大於等於10小於20的表的結構。

邏輯運算符:

And &&
Or ||
Not !
Xor

邏輯運算符與null的運算:

非:not !,非null 爲null
與:and &&,有0就是0,都是非零爲1,存在null與非零則爲null
或:or || , null||null=null null||1=1 null||0=null
異或: xor ,有null,就是null

mysql> select !null;
+-------+
| !null |
+-------+
|  NULL |
+-------+
1 row in set (0.00 sec)

mysql> select null;
+------+
| NULL |
+------+
| NULL |
+------+
1 row in set (0.00 sec)

mysql> select 0 && null;
+-----------+
| 0 && null |
+-----------+
|         0 |
+-----------+
1 row in set (0.00 sec)

mysql> select 1 && null;
+-----------+
| 1 && null |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)

mysql> select null || 1;
+-----------+
| null || 1 |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

mysql> select null || 0;
+-----------+
| null || 0 |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)

mysql> select null || null;
+--------------+
| null || null |
+--------------+
|         NULL |
+--------------+
1 row in set (0.00 sec)


group by子句


Group by 根據一個或多個列對結果集進行分組,語法:
[GROUP BY {col_name | expr | position} [ASC | DESC], ... [WITH ROLLUP]]

分組後,每組內顯示一條記錄:
原則上,分組後,查詢字段應該只有分組字段,但是可以有其他字段。此時其他字段就只是組內第一條記錄的信息,不能準確表示組內所有數據信息,因此通常不查詢其他字段。

分組後會利用分組字段進行排序顯示結果,默認爲asc升序,可以修改爲desc降序

可以使用多個字段進行分組,每個字段可以設置排序規則。

可以使用with rollup 進行組內聚合計算。

mysql> select t_name, gender, sum(days) from teacher_class where 1 group by t_name;
+--------+--------+-----------+
| t_name | gender | sum(days) |
+--------+--------+-----------+
| 李白       | male   |        41 |
| 韓信       | male   |        63 |
| 韓非       | secret |        15 |
+--------+--------+-----------+
3 rows in set (0.02 sec)
以上代碼表明姓名相同的數據顯示在同一格上邊,並統計天數之和。

注意:如果合計函數使用時,沒有與groupby 配合,統計所有的數據,將所有的數據當作一組。

mysql> select sum(days) from teacher_class where 1;
+-----------+
| sum(days) |
+-----------+
|       119 |
+-----------+
1 row in set (0.01 sec)

默認是升序的asc,可以使用group by時修改爲降序desc

mysql> select * from teacher_class where 1 group by t_name order by days asc;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  1 | 韓信       | male   | php0115 | 207  |   21 | 2013-01-15 | 2013-02-20 |
+----+--------+--------+---------+------+------+------------+------------+


mysql> select * from teacher_class where 1 group by t_name order by days desc;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  1 | 韓信       | male   | php0115 | 207  |   21 | 2013-01-15 | 2013-02-20 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  6 | 韓非       | secret | php0115 | 207  |   15 | 2013-03-27 | 2013-04-18 |
+----+--------+--------+---------+------+------+------------+------------+
3 rows in set (0.00 sec)

使用組合字段進行分組,
mysql> select t_name,c_name, sum(days) from teacher_class where 1 group by t_name, c_name;
+--------+---------+-----------+
| t_name | c_name  | sum(days) |
+--------+---------+-----------+
| 李白       | php0115 |        20 |
| 李白       | php0228 |        21 |
| 韓信       | php0115 |        21 |
| 韓信       | php0228 |        18 |
| 韓信       | php0331 |        24 |
| 韓非       | php0115 |        15 |
+--------+---------+-----------+
6 rows in set (0.00 sec)
上述代碼表明只有t_name和c_name都相同的纔會分爲一組。


rollup

使用 with rollup ,可以相當於利用組合條進行統計後,再使用上一條件再次統計一次。

mysql> select t_name,c_name, sum(days) from teacher_class where 1 group by t_name, c_name with rollup
    ->
    -> ;
+--------+---------+-----------+
| t_name | c_name  | sum(days) |
+--------+---------+-----------+
| 李白       | php0115 |        20 |
| 李白       | php0228 |        21 |
| 李白       | NULL    |        41 |
| 韓信       | php0115 |        21 |
| 韓信       | php0228 |        18 |
| 韓信       | php0331 |        24 |
| 韓信       | NULL    |        63 |
| 韓非       | php0115 |        15 |
| 韓非       | NULL    |        15 |
| NULL   | NULL    |       119 |
+--------+---------+-----------+
10 rows in set (0.00 sec)
注意,會統計到 沒有分組的情況,整個都是一組的情況:
上述代碼,李白、韓信、韓非分別又統計了一次,整個表由重新統計了一次,不相同的部分用NULL表示。

是否可以得到 大於某些代課天數的講師信息?

mysql> select t_name, sum(days) from teacher_class where sum(days)>=35 group by t_name;
ERROR 1111 (HY000): Invalid use of group function

分析發現:
where先執行,group by 後執行。sum()在計算的時候,沒有分組的呢。
無法在在where內使用合計函數:

having子句


參考select語句的執行順序:
From -> where -> select -> group by ->
可以知道,where負責先獲得結果,而如果需要在結果中再次處理(例如通過結果統計出來的聚合結果),則不能再使用where,此時where已經執行完畢,因此此時SQL提供給應該使用having再次執行過濾操作。

在 SQL 中增加 HAVING 子句原因是,WHERE 關鍵字無法與合計函數一起使用。
having與where類似,可篩選數據,where後的表達式怎麼寫,having就怎麼寫。不過having可以使用字段別名

having子句負責在結果(where查詢到的)中進行再次過濾,可以像使用where一樣,having進行處理:

mysql> select * from teacher_class where days >=20;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  1 | 韓信       | male   | php0115 | 207  |   21 | 2013-01-15 | 2013-02-20 |
|  3 | 韓信       | male   | php0331 | 102  |   24 | 2013-03-31 | 2013-05-05 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
|  5 | 李白       | male   | php0228 | 204  |   21 | 2013-03-31 | 2013-04-29 |
+----+--------+--------+---------+------+------+------------+------------+
4 rows in set (0.00 sec)


mysql> select * from teacher_class where days >=20 having room=207;
+----+--------+--------+---------+------+------+------------+------------+
| id | t_name | gender | c_name  | room | days | begin_date | end_date   |
+----+--------+--------+---------+------+------+------------+------------+
|  1 | 韓信       | male   | php0115 | 207  |   21 | 2013-01-15 | 2013-02-20 |
|  4 | 李白       | male   | php0115 | 207  |   20 | 2013-02-22 | 2013-03-25 |
+----+--------+--------+---------+------+------+------------+------------+
2 rows in set (0.00 sec)
having子句負責在where已經過濾的數據基礎之上進一步過濾。

mysql> select t_name, sum(days) from teacher_class where 1 group by t_name having sum(days)>35;
+--------+-----------+
| t_name | sum(days) |
+--------+-----------+
| 李白       |        41 |
| 韓信       |        63 |
+--------+-----------+
2 rows in set (0.00 sec)



集合函數







平均值:AVG([DISTINCT] expr)
統計數目:COUNT(expr),統計非null值的數目 count(*)可以返回所有的記錄
最大最小值:MIN([DISTINCT] expr), MAX([DISTINCT] expr)
計算總和:SUM([DISTINCT] expr)
組內連接:GROUP_CONCAT(expr)

合計函數通常與group by 一起使用,用於統計組內的信息。
但是可以單獨使用,相當於將所有行看成一組。


通常合計函數是不統計null值的。


mysql> select t_name, sum(days) from teacher_class where 1 group by t_name having sum(days)>35;
+--------+-----------+
| t_name | sum(days) |
+--------+-----------+
| 李白       |        41 |
| 韓信       |        63 |
+--------+-----------+
2 rows in set (0.00 sec)

mysql> select t_name, avg(days) from teacher_class where 1 group by t_name;
+--------+-----------+
| t_name | avg(days) |
+--------+-----------+
| 李白       |   20.5000 |
| 韓信       |   21.0000 |
| 韓非       |   15.0000 |
+--------+-----------+
3 rows in set (0.00 sec)

mysql> select t_name, max(days) from teacher_class where 1 group by t_name;
+--------+-----------+
| t_name | max(days) |
+--------+-----------+
| 李白       |        21 |
| 韓信       |        24 |
| 韓非       |        15 |
+--------+-----------+
3 rows in set (0.00 sec)

mysql> select t_name, min(days) from teacher_class where 1 group by t_name;
+--------+-----------+
| t_name | min(days) |
+--------+-----------+
| 李白       |        20 |
| 韓信       |        18 |
| 韓非       |        15 |
+--------+-----------+
3 rows in set (0.00 sec)

mysql> select t_name, count(days) from teacher_class where 1 group by t_name;
+--------+-------------+
| t_name | count(days) |
+--------+-------------+
| 李白       |           2 |
| 韓信       |           3 |
| 韓非       |           1 |
+--------+-------------+
3 rows in set (0.00 sec)


mysql> select count(*) from teacher_class;
+----------+
| count(*) |
+----------+
|        6 |
+----------+
1 row in set (0.00 sec)

mysql> select t_name, max(days) from teacher_class;
+--------+-----------+
| t_name | max(days) |
+--------+-----------+
| 韓信       |        24 |
+--------+-----------+
1 row in set (0.00 sec)
從所有行中挑選出天數做最大的一個。

mysql> select avg(days) from teacher_class;
+-----------+
| avg(days) |
+-----------+
|   19.8333 |
+-----------+
1 row in set (0.00 sec)
統計出所有的人數平均的天數。


mysql> select t_name, concat(t_name, id) from teacher_class;
+--------+--------------------+
| t_name | concat(t_name, id) |
+--------+--------------------+
| 韓信       | 韓信1                  |
| 韓信       | 韓信2                  |
| 韓信       | 韓信3                  |
| 李白       | 李白4                  |
| 李白       | 李白5                  |
| 韓非       | 韓非6                  |
+--------+--------------------+
6 rows in set (0.00 sec)
將每一行數據進行聯合


mysql> select t_name, group_concat(t_name, id) from teacher_class;
+--------+-------------------------------------+
| t_name | group_concat(t_name, id)            |
+--------+-------------------------------------+
| 韓信       | 韓信1,韓信2,韓信3,李白4,李白5,韓非6
+--------+-------------------------------------+
1 row in set (0.00 sec)
將表中的信息進行聯合。












發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章