1. 程式人生 > 其它 >mysql 高階查詢語句(2))

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 概念

  1. 可以被當作是虛擬表或儲存查詢
  2. 檢視跟表格的不同是,表格中有實際儲存資料,而檢視是建立在表格之上的一個架構,它本身並不實際儲存資料。
  3. 視圖表的內容,是由select 查詢語句的結果決定的,所以,查詢的結果不能有相同的欄位名
  4. 臨時表在使用者退出或同資料庫的連線斷開後就自動消失了,而檢視不會消失。
  5. 檢視不含有資料,只儲存它的定義,它的用途一般可以簡化複雜的查詢。比如你要對幾個表進行連線查詢,而且還要進行統計排序等操作,寫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)