mysql 高階查詢語句(2))
mysql 高階查詢語句(2)
目錄1 子查詢
連線表格,在WHERE 子句或HAVING 子句中插入另一個SQL語句
格式
select 欄位名1 from 表格1 where 欄位2 [比較運算子] #子查詢的外查詢部分
(select 欄位1 from 表2 where 條件2 ); #子查詢的內查詢部分
可以是符號的運算子,例如 =、>、<、>=、<=;也可以是文字的運算子,例如 LIKE、IN、BETWEEN
# 以project表name欄位分組,project表name欄位值要能夠在在school.class表中查詢name欄位中找到,然後查詢 project 表中name欄位值和score 平均值。 mysql> select name,avg(score) from school.project group by name -> having name in (select name from school.class); +-------------+------------+ | name | avg(score) | +-------------+------------+ | houlu | 90.0000 | | linrui | 80.0000 | | wanglei | 66.6667 | | zhoujiazhen | 66.6667 | +-------------+------------+ 4 rows in set (0.00 sec) mysql> select name,avg(score) from school.project a group by a.name havingg a.name in (select b.name from school.class b); +-------------+------------+ | name | avg(score) | +-------------+------------+ | houlu | 90.0000 | | linrui | 80.0000 | | wanglei | 66.6667 | | zhoujiazhen | 66.6667 | +-------------+------------+ 4 rows in set (0.00 sec)
2 exists 測試查詢布林值是否為真
用來測試內查詢有沒有產生任何結果,類似布林值是否為真
如果有的話,系統就會執行外查詢的SQL語句,若是沒有的話,那整個SQL語句就不會產生任何結果
語法:SELECT “欄位” FROM “表格1” WHERE EXISTS (SELECT * FROM "表格2" WHERE “條件”);
#如果school.class裡有id值為1 的,則檢視 school.project表 select * from school.project where exists ( select * from school.class where id=1);
3 表連線查詢
(1)格式1
select 欄位 from 表1 聯結查詢關鍵字 表2 on 表1.表字段=表2.表字段
(2) 格式2
select 欄位 from 表1 聯結查詢關鍵字 表2 using(表字段)
3.1 inner join(內連線)
只返回兩個表中聯結欄位相等的行
# 檢視school.class 表 name 欄位 和 school.project 表 name欄位相同的行
mysql> select * from school.class a inner join school.project b on a.name=b.name;
或者 select * from school.class a inner join school.project b using(name);
+----+-------------+---------+-------------+-------+
| id | name | project | name | score |
+----+-------------+---------+-------------+-------+
| 7 | houlu | chanese | houlu | 100 |
| 5 | linrui | chanese | linrui | 80 |
| 3 | wanglei | chanese | wanglei | 40 |
| 6 | zhoujiazhen | chanese | zhoujiazhen | 60 |
| 6 | zhoujiazhen | math | zhoujiazhen | 60 |
| 5 | linrui | math | linrui | 60 |
| 3 | wanglei | math | wanglei | 100 |
| 7 | houlu | math | houlu | 90 |
| 7 | houlu | english | houlu | 80 |
| 3 | wanglei | english | wanglei | 60 |
| 6 | zhoujiazhen | english | zhoujiazhen | 80 |
| 5 | linrui | english | linrui | 100 |
+----+-------------+---------+-------------+-------+
12 rows in set (0.00 sec)
mysql> select * from school.class a inner join school.project b using(name);
+-------------+----+---------+-------+
| name | id | project | score |
+-------------+----+---------+-------+
| houlu | 7 | chanese | 100 |
| linrui | 5 | chanese | 80 |
| wanglei | 3 | chanese | 40 |
| zhoujiazhen | 6 | chanese | 60 |
| zhoujiazhen | 6 | math | 60 |
| linrui | 5 | math | 60 |
| wanglei | 3 | math | 100 |
| houlu | 7 | math | 90 |
| houlu | 7 | english | 80 |
| wanglei | 3 | english | 60 |
| zhoujiazhen | 6 | english | 80 |
| linrui | 5 | english | 100 |
+-------------+----+---------+-------+
12 rows in set (0.00 sec)
3.2 left join 左連線
返回包括左邊中的所有記錄和右表中聯結欄位相等的記錄
select * from school.class a left join school.project b on a.name=b.name;
3.3 right join右連線查詢
返回包括右表中的所有記錄和左邊中聯結欄位相等的記錄
select * from school.project a right join school.class b on a.name=b.name;
4 view 試圖
4.1 概念
- 可以被當作是虛擬表或儲存查詢
- 檢視跟表格的不同是,表格中有實際儲存資料,而檢視是建立在表格之上的一個架構,它本身並不實際儲存資料。
- 視圖表的內容,是由select 查詢語句的結果決定的,所以,查詢的結果不能有相同的欄位名
- 臨時表在使用者退出或同資料庫的連線斷開後就自動消失了,而檢視不會消失。
- 檢視不含有資料,只儲存它的定義,它的用途一般可以簡化複雜的查詢。比如你要對幾個表進行連線查詢,而且還要進行統計排序等操作,寫SQL語句會很麻煩的,用檢視將幾個表聯結起來,然後對這個檢視進行查詢操作,就和對一個表查詢一樣,很方便。
語法:
(1)建立檢視
create view 檢視名 as 'select 語句';
(2) 檢視有那些檢視
show table status where comment='view' \G
(3) 刪除檢視
drop view 檢視名;
#建立 檢視
mysql> create view V_avg_score as
-> select name,avg(score) from school.project
-> group by name
-> having name in (select name from school.class);
#檢視視圖表內容
select * from V_avf_score
#檢視所有的視圖表
show table status where comment='view' \G
#刪除視圖表 V_avg_score
drop view V_avg_score;
5 union 聯集
聯集,將連個sql 語句的結果合併起來,兩個sql語句所產生的欄位需要是同樣的資料種類
語法
(1) union: 生成結果的資料值將沒有重複,且按照欄位的順序進行排序
[select 語句1 ] union [select 語句2 ];
(2) unio all: 將生成結果的資料值都列出來,無論有無重複
[ select 語句1 ] union all [select 語句2];
#使用union 聯集有去重的效果
mysql> select name from class union select name from project;
#使用union all 聯集只是將前後查詢結果聯集在一起,並不去重
mysql> select name from class union all select name from project;
#不管是union 還是union all ,前後查詢的欄位值型別不同,並不影響合併
mysql> select id from class union select name from project;
6 取交集值(去重)
交集值,取兩個sql 語句結果的交集
6.1 方法一: inner join 內聯與 on/where/using 一起用取交集使用distinct去重
# 內聯和on/where/using 一起使用取交集,如果想要去重,則在加上distinct
select class.name from class inner join project where class.name=project.name;
select class.name from class inner join project on class.name=project.name;
select class.name from class inner join project using(name);
#加上distinct 去重
select distinct class.name from class inner join project using(name);
6.2 方法二:使用子查詢 和union all 聯集 配合group by 配合count函式 取交集並去重
此方法,當一張表裡有重複,而另一張裡卻又沒有,就會統計出錯,需要先使用 distinct 去重然後再聯集
select A.name from ( select name from class
union all select name from project ) A group by A.name having count(*) >1;
6.4 方法三 使用子查詢結合內聯,然後給group by 分組
select A.name from
( select B.name from class B inner join project C where B.name=C.name) A
group by A.name;
6.4 方法四 使用左聯或者右聯配合distinct去重
select distinct A.name from class A
left join project B using(name) where B.name is not null;
6.5 方法五:使用distinct 配合 where in過濾和 子查詢
select distinct name from class where name in (select name from project);
7 無交集
無交集是現實第一個sql語句的結果,且與第二個sql語句的沒有交集的結果,且沒有重複
#方法一
mysql> select distinct name from class where name not in (select name from project);
+----------+
| name |
+----------+
| zhangsan |
| lisi |
| dingcong |
+----------+
3 rows in set (0.00 sec)
#方法二:
mysql> select distinct A.name from class A left join project B using(name) where B.name is null;
+----------+
| name |
+----------+
| zhangsan |
| lisi |
| dingcong |
+----------+
3 rows in set (0.00 sec)
#方法三:
mysql> select A.name from
(select distinct name from class union all select distinct name from project) A
group by A.name having count(*)=1;
+----------+
| name |
+----------+
| dingcong |
| lisi |
| zhangsan |
+----------+
3 rows in set (0.00 sec)
8 case
case 是sql 用來做if-then -else 之類邏輯的關鍵字
語法(1):
select 欄位名 , case 欄位名
when 條件1 then 結果
when 條件2 then 結果
else 結果
end 新欄位名
from 表名 ;
條件/結果 可以是一個數值或這公式,else 字句和 新欄位名不是必須的。
語法(2:)
select 欄位名 , case
when 條件1 then 結果
when 條件2 then 結果
else 結果
end 新欄位名
from 表名;
8.1 簡單函式
mysql> select
-> name '名字' ,
-> case name
-> when 'linrui' then
-> '掃地'
-> when 'zhoujiazhen' then
-> '拖地'
-> else
-> '擦窗子'
-> end '工作'
-> from
-> project;
#這裡沒有將查詢結果分組顯示,
8.2 搜尋函式
mysql> select
-> name '名字' ,
-> avg(score) '平均分' ,
-> case
-> when avg(score) < 60 then
-> '打屁股'
-> when avg(score) <70 then
-> '打手心'
-> when avg(score) <80 then
-> '鼓勵鼓勵'
-> when avg(score) <90 then
-> '還不錯,獎勵一根棒棒糖'
-> else
-> '優秀,非常好,獎勵三本練習題'
-> end '期末考試獎懲'
-> from
-> project group by name;
+-------------+-----------+--------------------------------------------+
| 名字 | 平均分 | 期末考試獎懲 |
+-------------+-----------+--------------------------------------------+
| houlu | 90.0000 | 優秀,非常好,獎勵三本練習題 |
| linrui | 80.0000 | 還不錯,獎勵一根棒棒糖 |
| wanglei | 66.6667 | 打手心 |
| zhoujiazhen | 66.6667 | 打手心 |
+-------------+-----------+--------------------------------------------+
4 rows in set (0.00 sec)