SQL基礎(2)

以前的SQL基礎1中已經介紹了部分Select的內容,可是,實際使用中select 還有不少其餘的用法,本文會再介紹部分select的其餘用法。mysql

1.  去重查詢

1.1  建立演示表

建立2張表用於演示,表名分別爲student和class,後續也將繼續用這2張表演示,2張表的數據以下:sql

student表測試

class表優化

 

 

 1.2  查詢student表的全部class_no內容

mysql> select  class_no from  student;
+----------+
| class_no |
+----------+
| 201801   |
| 201901   |
| 201901   |
| 201902   |
| 201902   |
| 201902   |
| 201902   |
+----------+

可見,查詢結果中不少重複的狀況。spa

1.3  去重查詢全部的class_no

去重使用 DISTINCT 關鍵字便可code

mysql> select  distinct class_no from  student;
+----------+
| class_no |
+----------+
| 201801   |
| 201901   |
| 201902   |
+----------+
3 rows in set (0.00 sec)

2.  條件查詢

條件查詢能夠有不少種組合,其中用 AND 或 OR鏈接不一樣的條件,同時能夠用in  , not in , >、>=、 <、<=、 =等條件進行範圍查詢等blog

2.1  AND條件

AND的意義至關於「且」,也就是AND先後的條件必須同時成立,例如:排序

查詢class_no爲201901 而且age>=22的學生索引

mysql> select  * from student where age>=22 and class_no='201901';
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  1 | 李白     |   25 | 201901   |
+----+----------+------+----------+
1 row in set (0.00 sec)

2.2  OR條件

OR意味着「或」,即OR先後條件中的一個知足條件及成立,例如:it

查詢student表中age>=24 後者班級號爲201801的學生

mysql> select  * from student where age>=24 or  class_no='201801';
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  1 | 李白     |   25 | 201901   |
|  4 | 喬峯     |   30 | 201801   |
|  7 | 杜甫     |   24 | 201902   |
+----+----------+------+----------+
3 rows in set (0.00 sec)

2.3  AND和OR的優先級

AND和OR的優先級順序是 AND大於OR,有括號的 先處理括號的 。即 AND和OR同時出現時,先處理AND 再與OR判斷,可是出現括號,有出現括號的先處理括號裏的。例如:

/**  沒有括號 先處理and 最後處理or   **/
mysql> select  * from student where age<23  and class_no='201902'  or  class_no='201801';
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
|  3 | 王維     |   21 | 201902   |
|  5 | 陳六     |   22 | 201902   |
+----+----------+------+----------+
3 rows in set (0.00 sec)

/**  有括號時,先庫哦李括號裏的or,最後處理 外層的AND ** /
mysql> select  * from student where age<23  and (class_no='201902'  or  class_no='201801');
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  3 | 王維     |   21 | 201902   |
|  5 | 陳六     |   22 | 201902   |
+----+----------+------+----------+
2 rows in set (0.00 sec)

建議: 實際使用時,若是嵌套的關係太多,當肯定須要先處理哪一個關係時建議都加上括號,已避免寫法錯誤致使結果與預期不一致。

2.4 IN或NOT IN

IN 或 NOT IN的使用頻率也是很是高的,例如:

/**  in  **/
mysql> select * from  student where class_no in ('201901','201902');
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  1 | 李白     |   25 | 201901   |
|  2 | 蘇軾     |   20 | 201901   |
|  3 | 王維     |   21 | 201902   |
|  5 | 陳六     |   22 | 201902   |
|  7 | 杜甫     |   24 | 201902   |
|  8 | 岳飛     |   23 | 201902   |
+----+----------+------+----------+
6 rows in set (0.00 sec)

/**  not in  **/
mysql> select * from  student where class_no  not in ('201901','201902');
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
+----+----------+------+----------+
1 row in set (0.00 sec)

3.  排序及分頁

3.1   排序

排序使用order  by來進行,能夠指定一個或多個字段進行排序,同時能夠指定升序(ASC,默認的是升序)或降序(DESC)。

/**   按照age升序排序 **/
mysql> select  * from  student order by age asc;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  2 | 蘇軾     |   20 | 201901   |
|  3 | 王維     |   21 | 201902   |
|  5 | 陳六     |   22 | 201902   |
|  8 | 岳飛     |   23 | 201902   |
|  7 | 杜甫     |   24 | 201902   |
|  1 | 李白     |   25 | 201901   |
|  4 | 喬峯     |   30 | 201801   |
+----+----------+------+----------+
7 rows in set (0.00 sec)

/** 按照age降序排列  **/
mysql> select  * from  student order by age desc;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
|  1 | 李白     |   25 | 201901   |
|  7 | 杜甫     |   24 | 201902   |
|  8 | 岳飛     |   23 | 201902   |
|  5 | 陳六     |   22 | 201902   |
|  3 | 王維     |   21 | 201902   |
|  2 | 蘇軾     |   20 | 201901   |
+----+----------+------+----------+
7 rows in set (0.00 sec)

/**  先按照class_no升序,class_no 相同時按照age降序排列 **/
mysql> select  * from  student order by class_no,age desc;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
|  1 | 李白     |   25 | 201901   |
|  2 | 蘇軾     |   20 | 201901   |
|  7 | 杜甫     |   24 | 201902   |
|  8 | 岳飛     |   23 | 201902   |
|  5 | 陳六     |   22 | 201902   |
|  3 | 王維     |   21 | 201902   |
+----+----------+------+----------+
7 rows in set (0.00 sec)

注:當表的數據量較大時,建議排序字段上有索引。

3.2  分頁

分頁查詢在數據展現上是使用頻率很是高的功能之一,1其語法爲:

select field_names
from  tbname
where filter
order by oderby_fieldname
limit offset,row_counts

其中 offset是偏移量,即以前遍歷了的數據量,row_counts指每頁的數據量。

例如,分頁遍歷其中一個表的記錄,每頁3條記錄,例如:

/** 首頁  **/

mysql> select  *  from  student order  by id  limit 3*0,3;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  1 | 李白     |   25 | 201901   |
|  2 | 蘇軾     |   20 | 201901   |
|  3 | 王維     |   21 | 201902   |
+----+----------+------+----------+
3 rows in set (0.00 sec)

/**  第二頁 **/
mysql> select  *  from  student order  by id  limit 3*1,3;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
|  5 | 陳六     |   22 | 201902   |
|  7 | 杜甫     |   24 | 201902   |
+----+----------+------+----------+
3 rows in set (0.00 sec)

/**  第三頁 **/
mysql> select  *  from  student order  by id  limit 3*2,3;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  8 | 岳飛     |   23 | 201902   |
+----+----------+------+----------+
1 row in set (0.00 sec)

注:  order  by 的字段上必定要有索引,不然 可能遍歷額結果有重複,相關例子能夠自行測試。

4.  聚合查詢

不少狀況下,咱們都須要進行一些彙總類的操做,即聚合查詢。聚合查詢一般須要配合GROUP BY關鍵字進行分組聚合。下面使用幾種常見的聚合查詢操做。

4.1  count

count是指統計記錄條數。

4.1.1 不分組的狀況下的聚合:

/** 查看student表的記錄總數 **/
mysql> select  count(*) from  student;
+----------+
| count(*) |
+----------+
|        7 |
+----------+
1 row in set (0.00 sec)

/**  查詢age大於24的記錄數  **/
mysql> select  count(*) from  student where age>=24;
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.00 sec)

4.1.2 分組狀況下聚合:

/** 按照class_no分組統計,即查詢每一個班級的人數 **/
mysql> select class_no, count(*) from student group by class_no; +----------+----------+ | class_no | count(*) | +----------+----------+ | 201801 | 1 | | 201901 | 2 | | 201902 | 4 | +----------+----------+ 3 rows in set (0.00 sec) /**查詢每一個班級的人數,同時按照人數降序排列 **/ mysql> select class_no, count(*) from student group by class_no order by count(*) desc ; +----------+----------+ | class_no | count(*) | +----------+----------+ | 201902 | 4 | | 201901 | 2 | | 201801 | 1 | +----------+----------+ 3 rows in set (0.00 sec)

/**查詢每一個班級的人數,同時只返回人數大於1個的class_no及人數 **/
mysql
> select class_no, count(*) from student group by class_no having count(*)>1 ; +----------+----------+ | class_no | count(*) | +----------+----------+ | 201901 | 2 | | 201902 | 4 | +----------+----------+ 2 rows in set (0.00 sec)

4.2 min、max 、avg 、sum

除了count的聚合操做外,還有min(最小)、max(最大) 、avg (平均)、sum(求和)等聚合操做,其操做和count相似。

例如:

mysql> select  max(age),min(age),avg(age),sum(age)  from  student;
+----------+----------+----------+----------+
| max(age) | min(age) | avg(age) | sum(age) |
+----------+----------+----------+----------+
|       30 |       20 |  23.5714 |      165 |
+----------+----------+----------+----------+
1 row in set (0.00 sec)

5. 子查詢

當進行查詢下的時候 須要查詢的條件是另一個select語句的結果的時候能夠用到子查詢來處理。此時要用in、not in 、exists、not  exists以及=、!=等。

例如:

/**  查詢存在於class表的student的記錄 **/
mysql> select  *  from  student where  class_no in (select class_no from class);
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  1 | 李白     |   25 | 201901   |
|  2 | 蘇軾     |   20 | 201901   |
|  3 | 王維     |   21 | 201902   |
|  5 | 陳六     |   22 | 201902   |
|  7 | 杜甫     |   24 | 201902   |
|  8 | 岳飛     |   23 | 201902   |
+----+----------+------+----------+
6 rows in set (0.00 sec)

/**  查詢不存在於class表的student的記錄 **/
mysql> select  *  from  student where  class_no not  in (select class_no from class);
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
+----+----------+------+----------+
1 row in set (0.00 sec)

exists和not exists在此時(子查詢不存在null的狀況下)查詢結果是等價的(查詢效率有差別,且和數據量有關),對於此問題,各位能夠本身測一下。

6. 錶鏈接

當須要同時展現多個表的字段時,須要用錶鏈接的方式將多張表的字段在一個查詢中展現。

錶鏈接的方式從大類上來講能夠分爲內鏈接和外鏈接。

6.1  內鏈接

內鏈接是查詢2張表同時存在的記錄,即兩張表的交集。

例如:

/**  同時查詢兩張表中class_no 相同的student及class表的全部字段內容 **/
mysql> select  * from  student a,class b 
    -> where a.class_no=b.class_no;
+----+----------+------+----------+----------+--------------+------------------+
| id | stu_name | age  | class_no | class_no | class_name   | location         |
+----+----------+------+----------+----------+--------------+------------------+
|  1 | 李白     |   25 | 201901   | 201901   | 2019級01班   | 博學北樓A401     |
|  2 | 蘇軾     |   20 | 201901   | 201901   | 2019級01班   | 博學北樓A401     |
|  3 | 王維     |   21 | 201902   | 201902   | 2019級02班   | 博學北樓B401     |
|  5 | 陳六     |   22 | 201902   | 201902   | 2019級02班   | 博學北樓B401     |
|  7 | 杜甫     |   24 | 201902   | 201902   | 2019級02班   | 博學北樓B401     |
|  8 | 岳飛     |   23 | 201902   | 201902   | 2019級02班   | 博學北樓B401     |
+----+----------+------+----------+----------+--------------+------------------+
6 rows in set (0.00 sec)

注:

a)  例子中是列舉出全部字段,全部能夠用* ,當須要列出指定字段時,能夠列出指定字段名展現,經過表名.字段名的方式列出

b)   內鏈接的寫法能夠向上述例子中那樣,也能夠用inner join  ... on...這種方式來寫,其中inner能夠省略,例如:

mysql> select  a.stu_name,b.class_name  from  student a  inner join class b  on a.class_no=b.class_no;
+----------+--------------+
| stu_name | class_name   |
+----------+--------------+
| 李白     | 2019級01班   |
| 蘇軾     | 2019級01班   |
| 王維     | 2019級02班   |
| 陳六     | 2019級02班   |
| 杜甫     | 2019級02班   |
| 岳飛     | 2019級02班   |
+----------+--------------+
6 rows in set (0.00 sec)

c) in能夠用內鏈接的方式來改寫,尤爲是多層子查詢時,這也是SQL優化中給的一種方案。例如以前in例子就能夠改寫爲:

mysql> select  distinct  a.*  from  student a  inner join class b  on a.class_no=b.class_no;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  1 | 李白     |   25 | 201901   |
|  2 | 蘇軾     |   20 | 201901   |
|  3 | 王維     |   21 | 201902   |
|  5 | 陳六     |   22 | 201902   |
|  7 | 杜甫     |   24 | 201902   |
|  8 | 岳飛     |   23 | 201902   |
+----+----------+------+----------+
6 rows in set (0.00 sec)

6.2  外鏈接

外鏈接分爲左鏈接和右鏈接,其中:

a) 左鏈接是指包含左邊表中的記錄,即便左表中含有和右表匹配不上的記錄也會保留。

b) 右鏈接是指包含右邊表中的記錄,即便右表中含有和左表匹配不上的記錄也會保留。

例如:

/** 左鏈接 **/
mysql> select  a.stu_name,b.class_name  from  student a   left join class b  on a.class_no=b.class_no;
+----------+--------------+
| stu_name | class_name   |
+----------+--------------+
| 李白     | 2019級01班   |
| 蘇軾     | 2019級01班   |
| 王維     | 2019級02班   |
| 陳六     | 2019級02班   |
| 杜甫     | 2019級02班   |
| 岳飛     | 2019級02班   |
| 喬峯     | NULL         |     /** 改記錄的class_no不存在與右表中 **/
+----------+--------------+
7 rows in set (0.00 sec)

/**  右鏈接 **/
mysql> select  a.stu_name,b.class_name  from  student a  right join class b  on a.class_no=b.class_no;
+----------+--------------+
| stu_name | class_name   |
+----------+--------------+
| 李白     | 2019級01班   |
| 蘇軾     | 2019級01班   |
| 王維     | 2019級02班   |
| 陳六     | 2019級02班   |
| 杜甫     | 2019級02班   |
| 岳飛     | 2019級02班   |
+----------+--------------+

注: 也可使用外鏈接來改寫not in ,例如以前not in的例子能夠按照以下方式改寫:

mysql> select  distinct a.*   from  student a   left join class b  on a.class_no=b.class_no where  b.class_no is null;
+----+----------+------+----------+
| id | stu_name | age  | class_no |
+----+----------+------+----------+
|  4 | 喬峯     |   30 | 201801   |
+----+----------+------+----------+
1 row in set (0.00 sec)

 

7. 記錄聯合

記錄聯合是指將多個查詢結果合併到一塊兒展現,須要用到UNION 、UNION ALL 關鍵字,其中UNION ALL不對多個查詢的結果去重,所有展現出來(即便查詢結果徹底相同),union 會對結果中的重複記錄進行去重後展現。

例如:

/**  union  all **/
mysql> select  a.stu_name,b.class_name  from  student a   left join class b  on a.class_no=b.class_no
    -> union all
    -> select  a.stu_name,b.class_name  from  student a   right join class b  on a.class_no=b.class_no;
+----------+--------------+
| stu_name | class_name   |
+----------+--------------+
| 李白     | 2019級01班   |
| 蘇軾     | 2019級01班   |
| 王維     | 2019級02班   |
| 陳六     | 2019級02班   |
| 杜甫     | 2019級02班   |
| 岳飛     | 2019級02班   |
| 喬峯     | NULL         |
| 李白     | 2019級01班   |
| 蘇軾     | 2019級01班   |
| 王維     | 2019級02班   |
| 陳六     | 2019級02班   |
| 杜甫     | 2019級02班   |
| 岳飛     | 2019級02班   |
+----------+--------------+
13 rows in set (0.00 sec)

/** union  **/
mysql> select  a.stu_name,b.class_name  from  student a   left join class b  on a.class_no=b.class_no
    -> union
    ->  select  a.stu_name,b.class_name  from  student a   right join class b  on a.class_no=b.class_no;
+----------+--------------+
| stu_name | class_name   |
+----------+--------------+
| 李白     | 2019級01班   |
| 蘇軾     | 2019級01班   |
| 王維     | 2019級02班   |
| 陳六     | 2019級02班   |
| 杜甫     | 2019級02班   |
| 岳飛     | 2019級02班   |
| 喬峯     | NULL         |
+----------+--------------+
7 rows in set (0.00 sec)
相關文章
相關標籤/搜索