1. 程式人生 > >MySQL單表查詢詳細解析

MySQL單表查詢詳細解析

一、關鍵字的執行優先順序

  1,from:找到表

  2,where:拿著where指定的約束條件,去檔案/表中取出一條條資料

  3,group by:將取出的一條條資料進行分組,如果沒有group by,則整體作為一組

  4,having:將分組的結果進行having過濾

  5,select:執行select

  6,distinct:去重

  7,order by:將結果按條件排序

  8,limit:限制結果的顯示條數

二、去重,四則運算,自定義顯示

#避免重複DISTINCT
  SELECT post FROM employee;#直接這樣查詢我們會看到很多重複的內容,我只想看一下有哪些職位,那麼多重複的內容是沒用的,所以我們加一個去重的功能,叫做distinct
  SELECT DISTINCT post FROM employee;  #對查詢出來的記錄進行去重,如果post職位有重複的,就會被剔除,剩下不重複的內容,注意,因為我們查詢出來的記錄裡面只有一個欄位post,才會根據post來進行去重
  SELECT DISTINCT post,salary FROM employee;#但是如果這樣寫,你會發現,貌似沒有起到根據post來去重的效果,因為你的去重條件變成了post和salary兩個欄位的資料,只有他倆合起來是一個重複記錄的時候才會去重  #通過四則運算查詢
    SELECT name, salary*12 FROM employee; #查詢每個人的年薪,月薪我們有記錄,查年薪呢?簡單的乘以12就可以了,from 庫.表的時候,我們已經通過use 庫名;來指定了庫了,所以from的時候直接寫from 表,就行了
    #你會發現,結果是出來了,但是我們的那個薪資的欄位名變成了salary*12,是因為我們通過查詢語句查詢出來的也是一張表,但是這個表是不是記憶體當中的一個虛擬表,並不是我們硬碟中存的那個完整的表,對吧,虛擬表是不是也有標題和記錄啊,
既然是一個表,我們是可以指定這個虛擬表的標題的,通過as+新欄位名來指定
    SELECT name, salary*12 AS Annual_salary FROM employee; #as + 新欄位名,就是起一個別名的意思,上面的那個salary*12的欄位名也是一個別名,只不過不直觀,是mysql自動給你寫上的
  #除了乘法以外,加減乘除都是可以的
#自定義顯示格式,自己規定查詢結果的顯示格式
  CONCAT() 函式用於連線字串
  SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary  #我想讓name這個欄位顯示的欄位名稱是中文的姓名,讓salary*12顯示的是中文的年薪,
  FROM employee;#看結果:通過結果你可以看出,這個concat就是幫我們做字串拼接的,並且拼接之後的結果,都在一個叫做Annual_salary的欄位中了
    +---------------------------------------+
    | Annual_salary                        |
    +---------------------------------------+
    | 姓名: egon  年薪: 87603.96            |
    | 姓名: alex  年薪: 12000003.72        |
    | 姓名: wupeiqi  年薪: 99600.00        |
    | 姓名: yuanhao  年薪: 42000.00        |
    .....
      +---------------------------------------+
  SELECT CONCAT('姓名: ',name,'  年薪: ', salary*12)  AS Annual_salary,CONCAT('性別:',sex) from employee;#還可以這樣分成兩列  
  CONCAT_WS() 第一個引數為分隔符來進行字串拼接
  SELECT CONCAT_WS(':',name,salary*12)  AS Annual_salary from employee; #通過冒號來將name和salary連線起來#上面這個效果我們也可以通過concat來實現:SELECT CONCAT(name,':',salary*12)  AS Annual_salary from employee;

三、where約束

  1,比較運算子:> < >= <= <> !=

  2,between 80 and 100

  3,in(80,90,100)

  4,like 'ee%' 模糊匹配,%表示任意多字元,_表示一個字元

  5,邏輯運算子:在多個條件直接可以用邏輯運算子 and or not

#1:單條件查詢
    SELECT name FROM employee WHERE post='sale';  #注意優先順序,我們說where的優先順序是不是比select要高啊,所以我們的順序是先找到這個employee表,然後按照post='sale'的條件,然後去表裡面select資料
#2:多條件查詢
    SELECT name,salary FROM employee WHERE post='teacher' AND salary>10000;
#3:關鍵字BETWEEN AND 寫的是一個區間
    SELECT name,salary FROM employee  WHERE salary BETWEEN 10000 AND 20000; #就是salary>=10000 and salary<=20000的資料
    SELECT name,salary FROM employee  WHERE salary NOT BETWEEN 10000 AND 20000; #加個not,就是不在這個區間內,薪資小於10000的或者薪資大於20000的,注意沒有等於,
#4:關鍵字IS NULL(判斷某個欄位是否為NULL不能用等號,需要用IS) 判斷null只能用is
    SELECT name,post_comment FROM employee WHERE post_comment IS NULL;
    SELECT name,post_comment FROM employee WHERE post_comment IS NOT NULL#5:關鍵字IN集合查詢
    SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; #這樣寫是不是太麻煩了,寫一大堆的or,下面我們用in這個簡單的寫法來搞
    SELECT name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ;
    SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ;
#6:關鍵字LIKE模糊查詢,模糊匹配,可以結合萬用字元來使用
    萬用字元’%’  #匹配任意所有字元
    SELECT * FROM employee WHERE name LIKE 'eg%';
    萬用字元’_’  #匹配任意一個字元 
    SELECT * FROM employee WHERE name LIKE 'al__'; #注意我這裡寫的兩個_,用1個的話,匹配不到alex,因為al後面還有兩個字元ex。

四、分組查詢group by

select * from 表名 group by 欄位 
對sql_mode進行設定為ONLY_FULL_GROUP_BY,此時就會報錯,只能檢視該欄位的內容,但如果沒有設定,也只會顯示每組的第一組資料

單獨使用GROUP BY關鍵字分組
    SELECT post FROM employee GROUP BY post;
    注意:我們按照post欄位分組,那麼select查詢的欄位只能是post,想要獲取組內的其他相關資訊,需要藉助函式
GROUP BY關鍵字和GROUP_CONCAT()函式一起使用,比如說我想按部門分組,每個組有哪些員工,都顯示出來,怎麼搞
    SELECT post,GROUP_CONCAT(name) FROM employee GROUP BY post;#按照崗位分組,並檢視組內所有成員名,通過逗號拼接在一起
    SELECT post,GROUP_CONCAT(name,':',salary) as emp_members FROM employee GROUP BY post;
GROUP BY一般都會與聚合函式一起使用,聚合是什麼意思:聚合就是將分組的資料聚集到一起,合併起來搞事情,拿到一個最後的結果
    select post,count(id) as count from employee group by post;#按照崗位分組,並檢視每個組有多少人,每個人都有唯一的id號,我count是計算一下分組之後每組有多少的id記錄,通過這個id記錄我就知道每個組有多少人了
關於集合函式,mysql提供了以下幾種聚合函式:count、max、min、avg、sum等,上面的group_concat也算是一個聚合函數了,做字串拼接的操作

五、過濾having

執行優先順序:where,group by,having
where發生在group之前,因而where可以用任意欄位,但絕不能用聚合函式
having發生在group by之後,因而可以用分組的欄位,無法直接用到其他欄位,having是可以用聚合函式的
select post,avg(salary) from t1 where age > 30 group by post having avg(salary) >10000;
這是得到各部門年齡大於30的員工的平均工資,最後保留平均工資大於10000的部門

六、查詢排序order by

select * from t1 order by salary  #預設升序排列
select * from t1 order by salary asc;  #升序排列
select * from t1 order by salary desc;  #降序排列
select * from t1 order by age asc,salary desc;    #先以年齡升序排列,若年齡相同的就以工資降序排列

七、限制查詢的記錄數limit

select * from t1 order by salary limit 3;  #預設起始位為0,即從第一條資料開始,總共顯示3條資料
select * from t1 order by salary desc limit 0,5;  #起始位為0,即從第一條開始,總共顯示5條資料
select * from t1 order by salary asc limit 2,6;    #起始位為2,即從第三條開始,總共顯示6條資料

八、使用正則表示式查詢

之前用的like是模糊匹配,只有%和_,具有侷限性,查詢的時候其實可以用我們之前學正則
select * from t1 where name regexp '^ale';    #匹配以ale開頭的
select * from t1 where name regexp 'ss$';    #匹配以ss結尾的
select * from t1 where name regexp 'm{2}'      #匹配含有2個m的

對字串匹配的方式:
where name = 'ee'  #查詢name是‘ee’的資料
where name like 'yu%'  #查詢以yu開頭的資料
where name regexp 'euu$'  #查詢以euu結尾的資料