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)
列子句:
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可以省略,一個字段後面的標識符,就是當前的別名
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內的所有數據。交叉連接,笛卡爾積
mysql> select * from teacher_class,auin_1;
48 rows in set (0.00 sec)
中間表中的數據沒有列出。表可以是一個或者多個,使用逗號分割(參考多表操作)
虛擬表dual
mysql> select now() from dual;
+---------------------+
| now() |
+---------------------+
| 2016-08-05 20:16:56 |
+---------------------+
1 row in set (0.00 sec)
不建表而進行相關函數的查詢工作。
運算符
不等於:<> !=
小於,小於等於,大於,大於等於:< <= > >=
模糊匹配: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獲取一個元素的索引:
依次判斷值,與元素之間的大小關係,如果值小於元素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的表的結構。Or ||
Not !
Xor
與: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 {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)
以上代碼表明姓名相同的數據顯示在同一格上邊,並統計天數之和。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
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)
注意,會統計到 沒有分組的情況,整個都是一組的情況: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()在計算的時候,沒有分組的呢。
having子句
From -> where -> select -> group by ->
可以知道,where負責先獲得結果,而如果需要在結果中再次處理(例如通過結果統計出來的聚合結果),則不能再使用where,此時where已經執行完畢,因此此時SQL提供給應該使用having再次執行過濾操作。
having與where類似,可篩選數據,where後的表達式怎麼寫,having就怎麼寫。不過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)
集合函數
統計數目: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)
將表中的信息進行聯合。