day 38 MySQL之單表查詢

返回主頁

MySQL之單表查詢

 

一 單表查詢的語法

複製代碼
#查詢數據的本質:mysql會到你本地的硬盤上找到對應的文件,而後打開文件,按照你的查詢條件來找出你須要的數據。下面是完整的一個單表查詢的語法

select * from,這個select * 指的是要查詢全部字段的數據。
SELECT distinct 字段1,字段2... FROM 庫名.表名 #from後面是說從庫的某個表中去找數據,mysql會去找到這個庫對應的文件夾下去找到你表名對應的那個數據文件,找不到就直接報錯了,找到了就繼續後面的操做 WHERE 條件 #從表中找符合條件的數據記錄,where後面跟的是你的查詢條件 GROUP BY field(字段) #分組 HAVING 篩選 #過濾,過濾以後執行select後面的字段篩選,就是說我要肯定一下須要哪一個字段的數據,你查詢的字段數據進行去重,而後在進行下面的操做 ORDER BY field(字段) #將結果按照後面的字段進行排序 LIMIT 限制條數 #將最後的結果加一個限制條數,就是說我要過濾或者說限制查詢出來的數據記錄的條數

關於上面這些內容,咱們在下面一個一個的來詳細解釋
複製代碼

 

二 關鍵字的執行優先級(重點)

複製代碼
複製代碼
重點中的重點:關鍵字的執行優先級
from
where
group by
having
select
distinct
order by
limit
複製代碼
複製代碼

  1.找到表:frommysql

  2.拿着where指定的約束條件,去文件/表中取出一條條記錄正則表達式

  3.將取出的一條條記錄進行分組group by,若是沒有group by,則總體做爲一組sql

  4.將分組的結果進行having過濾windows

  5.執行select函數

  6.去重post

  7.將結果按條件排序:order by學習

  8.限制結果的顯示條數測試

       詳細見:https://www.cnblogs.com/clschao/articles/9995517.html網站

三 簡單查詢

複製代碼
#咱們來建立一個員工表,而後對員工表進行一個簡單的查詢,來看一下效果,下面是員工表的字段
company.employee 員工id id int 姓名 emp_name varchar 性別 sex enum 年齡 age int 入職日期 hire_date date 崗位 post varchar 職位描述 post_comment varchar 薪水 salary double 辦公室 office int 部門編號 depart_id int #建立表 create table employee( id int not null unique auto_increment, name varchar(20) not null, sex enum('male','female') not null default 'male', #大部分是男的 age int(3) unsigned not null default 28, hire_date date not null, post varchar(50), post_comment varchar(100), salary double(15,2), office int, #一個部門一個屋子 depart_id int ); #查看錶結構 mysql> desc employee; +--------------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(20) | NO | | NULL | | | sex | enum('male','female') | NO | | male | | | age | int(3) unsigned | NO | | 28 | | | hire_date | date | NO | | NULL | | | post | varchar(50) | YES | | NULL | | | post_comment | varchar(100) | YES | | NULL | | | salary | double(15,2) | YES | | NULL | | | office | int(11) | YES | | NULL | | | depart_id | int(11) | YES | | NULL | | +--------------+-----------------------+------+-----+---------+----------------+ #插入記錄 #三個部門:教學,銷售,運營 insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values ('egon','male',18,'20170301','老男孩駐沙河辦事處外交大使',7300.33,401,1), #如下是教學部,全都是老師 ('alex','male',78,'20150302','teacher',1000000.31,401,1), ('wupeiqi','male',81,'20130305','teacher',8300,401,1), ('yuanhao','male',73,'20140701','teacher',3500,401,1), ('liwenzhou','male',28,'20121101','teacher',2100,401,1), ('jingliyang','female',18,'20110211','teacher',9000,401,1), ('jinxin','male',18,'19000301','teacher',30000,401,1), ('成龍','male',48,'20101111','teacher',10000,401,1), ('歪歪','female',48,'20150311','sale',3000.13,402,2),#如下是銷售部門 ('丫丫','female',38,'20101101','sale',2000.35,402,2), ('丁丁','female',18,'20110312','sale',1000.37,402,2), ('星星','female',18,'20160513','sale',3000.29,402,2), ('格格','female',28,'20170127','sale',4000.33,402,2), ('張野','male',28,'20160311','operation',10000.13,403,3), #如下是運營部門 ('程咬金','male',18,'19970312','operation',20000,403,3), ('程咬銀','female',18,'20130311','operation',19000,403,3), ('程咬銅','male',18,'20150411','operation',18000,403,3), ('程咬鐵','female',18,'20140512','operation',17000,403,3) ; #ps:若是在windows系統中,插入中文字符,select的結果爲空白,能夠將全部字符編碼統一設置成gbk
複製代碼

 

  查詢操做:

複製代碼
簡單查詢
    SELECT id,name,sex,age,hire_date,post,post_comment,salary,office,depart_id 
    FROM employee;

    SELECT * FROM employee; #不推薦用* ,查詢的時候*的效率低,至於爲何低,後面會講到,先知道一下就好了

    SELECT name,salary FROM employee;

#避免重複DISTINCT
SELECT post FROM employee;#直接這樣查詢咱們會看到不少重複的內容,我只想看一下有哪些職位,那麼多重複的內容是沒用的,因此咱們加一個去重的功能,叫作distinct
  SELECT DISTINCT post FROM employee; #對查詢出來的記錄進行去重,若是post職位有重複的,就會被剔除,剩下不重複的內容,注意,由於咱們查詢出來的記錄裏面只有一個字段post,纔會根據post來進行去重
SELECT DISTINCT post,salary FROM employee;#可是若是這樣寫,你會發現,貌似沒有起到根據post來去重的效果,由於你的去重條件變成了post和salary兩個字段的數據,只有他倆合起來是一個重複記錄的時候纔會去重
  看一下下面這兩句的效果就明白了:注意一點,使用distinct對記錄進行去重的時候,distinct必須寫在全部查詢字段的前面,否則會報錯,固然有些特別的用法能夠結合着寫到字段的中間或者後面,這個後面學到了咱們再說
select post,sex from employee;
select distinct post,sex from employee;
#經過四則運算查詢 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自動給你寫上的 SELECT name, salary*12 Annual_salary FROM employee;   #除了乘法之外,加減乘除都是能夠的

#自定義顯示格式,本身規定查詢結果的顯示格式 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 #經過冒號來將name和salary鏈接起來 FROM employee; #上面這個效果咱們也能夠經過concat來實現:SELECT CONCAT(name,':',salary*12)  AS Annual_salary from employee; 結合CASE語句:結合條件來對查詢的結果進行一些加工操做 SELECT ( CASE WHEN NAME = 'egon' THEN NAME WHEN NAME = 'alex' THEN CONCAT(name,'_BIGSB') ELSE concat(NAME, 'SB') END ) as new_name,sex FROM employee;

#看結果:

    +--------------+--------+
    | new_name | sex |
    +--------------+--------+
    | egon | male |
    | alex_BIGSB | male |
    | wupeiqiSB | male |
    | yuanhaoSB | male |
    | liwenzhouSB | male |
    | jingliyangSB | female |
    | jinxinSB | male |
    | 成龍SB | male |

    ...

    +--------------+

 
複製代碼

   簡單查詢就結束了,咱們作一下練習,而後繼續學習咱們上面列舉完整查詢語句中的其餘內容。

  小練習:

1 查出全部員工的名字,薪資,格式爲
    <名字:egon>    <薪資:3000>
2 查出全部的崗位(去掉重複)
3 查出全部員工名字,以及他們的年薪,年薪的字段名爲annual_year

 

  答案

 

四 WHERE約束

  where語句中可使用:

    以前咱們用where 後面跟的語句是否是id=1這種類型的啊,用=號鏈接的,除了=號外,還能使用其餘的,看下面:

  1. 比較運算符:> < >= <= <> !=
  2. between 80 and 100 值在80到100之間
  3. in(80,90,100)  值是80或90或100
  4. like 'egon%'
      pattern能夠是%或_,
      %表示任意多字符
      _表示一個字符 
  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;
        
    SELECT name,post_comment FROM employee 
        WHERE post_comment=''; 注意''是空字符串,不是null,兩個是不一樣的東西,null是啥也沒有,''是空的字符串的意思,是一種數據類型,null是另一種數據類型
    ps:
        執行
        update employee set post_comment='' where id=2;
        再用上條查看,就會有結果了

#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。
複製代碼

 

where條件我們就說完了,這個where條件到底怎麼運做的,咱們來講一下:咱們以select id,name,age from employee where id>7;這個語句來講一下

  首先先找到employee表,找到這個表以後,mysql會拿着where後面的約束條件去表裏面找符合條件的數據,而後遍歷你表中全部的數據,查看一下id是否大於7,逐條的對比,而後只要發現id比7大的,它就會把這一整條記錄給select,可是select說我只拿id、name、age這個三個字段裏面的數據,而後就打印了這三個字段的數據,而後where繼續往下過濾,看看id是否是還有大於7的,而後發現一個符合條件的就給select一個,而後重複這樣的事情,直到把數據所有過濾一遍纔會結束。這就是where條件的一個工做方式。

 

而後咱們能夠來作一些小練習:

複製代碼
1. 查看崗位是teacher的員工姓名、年齡
2. 查看崗位是teacher且年齡大於30歲的員工姓名、年齡
3. 查看崗位是teacher且薪資在9000-1000範圍內的員工姓名、年齡、薪資
4. 查看崗位描述不爲NULL的員工信息
5. 查看崗位是teacher且薪資是10000或9000或30000的員工姓名、年齡、薪資
6. 查看崗位是teacher且薪資不是10000或9000或30000的員工姓名、年齡、薪資
7. 查看崗位是teacher且名字是jin開頭的員工姓名、年薪
複製代碼

 

  答案

 

五 分組查詢:GROUP BY

  一、 什麼是分組?爲何要分組?

    

複製代碼
#一、首先明確一點:分組發生在where以後,即分組是基於where以後獲得的記錄而進行的

#二、分組指的是:將全部記錄按照某個相同字段進行歸類,好比針對員工信息表的職位分組,或者按照性別進行分組等

#三、爲什麼要分組呢?是由於咱們有時候會須要以組爲單位來統計一些數據或者進行一些計算的,對不對,比方說下面的幾個例子
    取每一個部門的最高工資  
    取每一個部門的員工數
    取男人數和女人數  

    小竅門:‘每’這個字後面的字段,就是咱們分組的依據,只是個小竅門,可是不能表示全部的狀況,看上面第三個分組,沒有'每'字,這個就須要咱們經過語句來自行判斷分組依據了
    咱們能用id進行分組嗎,能,可是id是否是重複度很低啊,基本沒有重複啊,對不對,這樣的字段適合作分組的依據嗎?不適合,對不對,依據性別分組行不行,固然行,由於性別咱們知道,是否是就兩種啊,也可能有三種是吧,這個重複度很高,對不對,分組來查的時候纔有更好的意義
  
#四、大前提:
    能夠按照任意字段分組,可是分組完畢後,好比group by post,只能查看post字段,若是想查看組內信息,須要藉助於聚合函數

#注意一點,在查詢語句裏面select 字段 from 表,這幾項是必需要有的,其餘的什麼where、group by等等都是無關緊要的
複製代碼

  

  來,咱們來測試一下:

複製代碼
mysql> select * from employee group by post;
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name   | sex    | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 14 | 張野   | male   |  28 | 2016-03-11 | operation                               | NULL         |   10000.13 |    403 |         3 |
|  9 | 歪歪   | female |  48 | 2015-03-11 | sale                                    | NULL         |    3000.13 |    402 |         2 |
|  2 | alex   | male   |  78 | 2015-03-02 | teacher                                 | NULL         | 1000000.31 |    401 |         1 |
|  1 | egon   | male   |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使              | NULL         |    7300.33 |    401 |         1 |
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
4 rows in set (0.06 sec)

經過結果能夠看出,若是直接經過post部門字段來進行分組,默認拿到的結果都是每組的第一條數據
可是你想,咱們分組的意義是什麼,是否是說經過分組來統計一下整個組的狀況啊,再也不是看某我的單獨的狀況了,對不對,而且未來你在這樣進行直接分組查詢的時候,可能由於大家公司設置的mysql的環境不一樣,而查不到數據,咱們能夠看到,咱們如今仍然能夠查詢出來數據,可是若是咱們在sql_mode中添加了下面的only_full_group_by這個mode,那麼咱們在直接分組查詢,就沒法獲得數據了,只能獲得字段名
而且設置了sql_mode爲only_full_group_by以後,select *,就不行了,會直接報錯,只能select post ,post是你分組的那個字段
複製代碼

 

  二、 ONLY_FULL_GROUP_BY

 

複製代碼
#查看MySQL 5.7默認的sql_mode以下:
mysql> select @@global.sql_mode;
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

#!!!注意
ONLY_FULL_GROUP_BY的語義就是肯定select target list中的全部列的值都是明確語義,簡單的說來,在ONLY_FULL_GROUP_BY模式下,target list中的值要麼是來自於彙集函數的結果,要麼是來自於group by list中的表達式的值。


#設置sql_mole以下操做(咱們能夠去掉ONLY_FULL_GROUP_BY模式):
mysql> set global sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
複製代碼

 

    看一下測試:

複製代碼
mysql> select @@global.sql_mode;
+-------------------+
| @@global.sql_mode |
+-------------------+
|                   |
+-------------------+
1 row in set (0.00 sec)

mysql> select * from emp group by post; 
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| id | name | sex    | age | hire_date  | post                       | post_comment | salary     | office | depart_id |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
| 14 | 張野 | male   |  28 | 2016-03-11 | operation                  | NULL         |   10000.13 |    403 |         3 |
|  9 | 歪歪 | female |  48 | 2015-03-11 | sale                       | NULL         |    3000.13 |    402 |         2 |
|  2 | alex | male   |  78 | 2015-03-02 | teacher                    | NULL         | 1000000.31 |    401 |         1 |
|  1 | egon | male   |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使 | NULL         |    7300.33 |    401 |         1 |
+----+------+--------+-----+------------+----------------------------+--------------+------------+--------+-----------+
4 rows in set (0.00 sec)


#因爲沒有設置ONLY_FULL_GROUP_BY,因而也能夠有結果,默認都是組內的第一條記錄,但其實這是沒有意義的

mysql> set global sql_mode='ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected (0.00 sec)

mysql> quit #設置成功後,必定要退出,而後從新登陸方可生效
Bye

mysql> use db1;
Database changed
mysql> select * from emp group by post; #報錯
ERROR 1055 (42000): 'db1.emp.id' isn't in GROUP BY  #意思是告訴你,你select後面取的字段必須在你的group by後面的字段裏面才行
mysql> select post,count(id) from emp group by post; #只能查看分組依據和使用聚合函數 +----------------------------+-----------+ | post | count(id) | +----------------------------+-----------+ | operation | 5 | | sale | 5 | | teacher | 7 | | 老男孩駐沙河辦事處外交大使 | 1 | +----------------------------+-----------+ 4 rows in set (0.00 sec)

由於通常分組以後,咱們再考慮其中一條數據就沒有什麼意義了,因此通常咱們都會在這種模式下進行分組,下面咱們在看看group by,下面的內容

複製代碼

 

  三、 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也算是一個聚合函數了,作字符串拼接的操做
複製代碼

 

    強調:

若是咱們用設置了unique約束的字段做爲分組的依據,則每一條記錄自成一組,這種分組沒有意義
多條記錄之間的某個字段值相同,該字段一般用來做爲分組的依據

 

  四、 聚合函數

複製代碼
#強調:聚合函數聚合的是組的內容,如果沒有分組,則默認一組

示例:
    SELECT COUNT(*) FROM employee;  #count是統計個數用的
    SELECT COUNT(*) FROM employee WHERE depart_id=1;  #後面跟where條件的意思是統計一下知足depart_id=1這個的全部記錄的個數
    SELECT MAX(salary) FROM employee;  #max()統計分組後每組的最大值,這裏沒有寫group by,那麼就是統計整個表中全部記錄中薪資最大的,薪資的值
    SELECT MIN(salary) FROM employee;
    SELECT AVG(salary) FROM employee;
    SELECT SUM(salary) FROM employee;
    SELECT SUM(salary) FROM employee WHERE depart_id=3;
複製代碼

 

  五、 小練習:

複製代碼
1. 查詢崗位名以及崗位包含的全部員工名字
#經過上面的需求來整理邏輯:a、先看一下和哪一個表有關係:全部的信息都在employee這個表裏面,因此先寫from employee,找到表了
# b、看有沒有什麼過濾條件,大於小於啊什麼的,沒有吧,因此是否是不須要寫where條件啊
# c、看看有沒有分組的內容,也就是看看上面的需求裏面有沒有分類的概念,發現是否是有啊,按照崗位來分組,對不對,因此該寫什麼了:from employee group by post;
# d、而後再看須要查什麼字段出來,發現是否是要看崗位名和全部員工的名字啊,因此怎麼寫:select post,group_concat(name) from employee group by post;這就是完整語句了,不信你試試
下面的題都按照上面這個邏輯來搞一搞:
2. 查詢崗位名以及各崗位內包含的員工個數 3. 查詢公司內男員工和女員工的個數 4. 查詢崗位名以及各崗位的平均薪資 5. 查詢崗位名以及各崗位的最高薪資 6. 查詢崗位名以及各崗位的最低薪資 7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資。 #這道題咱們本身提煉一下分組依據,是否是就是性別啊

#總結:先from打開文件,而後按照where後面的條件,將硬盤的數據讀到內存,內存中的到一張虛擬表,而後按照虛擬表來進行group by分組。group by 必須寫在where條件以後,寫在where以前會報錯,語法規定的
#咱們說聚合函數是跟着分組來的,你看這樣一句話:select max(salary) from employee;直接也是可使用聚合函數的,由於沒有where,那麼默認是表中全部的數據,沒有group by,默認整個表是一組

8.統計各部門年齡在30歲及以上的員工平均薪資
#想一下怎麼寫,一、from 表 二、where age>=30獲得一張虛擬表 三、對虛擬表按部門group by 四、select 部門和聚合函數avg
#答案:select post,avg(salary) from employee where age>=30 group by post;
#看結果:

    mysql> select post,avg(salary) from employee where age>=30 group by post;#由於有的部門裏面的員工沒有大於30歲的,因此沒有顯示出全部的部門
    +---------+---------------+
    | post | avg(salary) |
    +---------+---------------+
    | sale | 2500.240000 |
    | teacher | 255450.077500 |
    +---------+---------------+
    2 rows in set (0.09 sec)

到這裏咱們的group by就講完了,看一下咱們完整查詢語句裏面還有什麼

SELECT distinct 字段1,字段2... FROM 庫名.表名 
                  WHERE 條件       
                  GROUP BY field(字段)   
                  HAVING 篩選      #過濾,過濾以後執行select後面的字段篩選,就是說我要肯定一下須要哪一個字段的數據,你查詢的字段數據進行去重,而後在進行下面的操做
                  ORDER BY field(字段)   #將結果按照後面的字段進行排序
                  LIMIT 限制條數
注意:雖然語法裏面咱們先寫的select,可是並非先執行的select,按照mysql本身的規範來執行的下面關鍵字的優先級
  from
  where
  group by
  having
  select
  distinct
  order by
  limit
複製代碼

 

  答案

 

六 HAVING過濾

  講having以前,咱們補充一個點:以前咱們寫的查詢語句是這樣的:select id,name from employee;實際上咱們在select每一個字段的時候,省略了一個表名,有的人可能會這樣寫,select employee.id,employee.name from employee;你會發現查詢出來的結果是同樣的,可是若是你要將查詢出來的結果表,起一個新表名的話,帶着表名這樣寫就錯了

  select employee.id,employee.name from employee as tb1;這樣執行會下面的報錯:

    mysql> select employee.id,employee.name from employee as tb1;
    ERROR 1054 (42S22): Unknown column 'employee.id' in 'field list'

 

  由於這個語句先執行的是誰啊,是否是咱們的from啊,那麼後面的as也是比select要先執行的,因此你先將表employee起了個新名字叫作tb1,而後在tb1裏面取查詢數據,那麼tb1裏面找不到employee.id這個字段,就會報錯,若是咱們查詢的時候不帶表名,你as來起一個新的表名也是沒問題的,簡單提一下這個內容,知道就行了

  

HAVING與WHERE不同的地方在於!!!!!!

having的語法格式和where是如出一轍的,只不過having是在分組以後進行的進一步的過濾,where不能使用聚合函數,having是可使用聚合函數的
#!!!執行優先級從高到低:where > group by > having #1. Where 發生在分組group by以前,於是Where中能夠有任意字段,可是絕對不能使用聚合函數。 #2. Having發生在分組group by以後,於是Having中可使用分組的字段,沒法直接取到其餘字段,having是可使用聚合函數

 

  having簡單測試:

複製代碼
#來個需求:統計各部門年齡在30歲及以上的員工的平均薪資,而且保留平均工資大於10000的部門
答案:select post,avg(salary) as new_sa from employee where age>=30 group by post having avg(salary) > 10000;
看結果:

  +---------+---------------+
  | post | new_sa |
  +---------+---------------+
  | teacher | 255450.077500 |
  +---------+---------------+
  1 row in set (0.00 sec)

而後咱們看這樣一句話:select * from employee having avg(salary) > 10000;
只要一運行就會報錯:

    mysql> select * from employee having avg(salary) > 10000;
    ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause

是由於having只能在group by後面運行

複製代碼

 

  小練習:

1. 查詢各崗位內包含的員工個數小於2的崗位名、崗位內包含員工名字、個數
3. 查詢各崗位平均薪資大於10000的崗位名、平均工資
4. 查詢各崗位平均薪資大於10000且小於20000的崗位名、平均工資

 

  答案

 

 

  說一下去重:distinct 

    將查詢的結果進行去重:select distinct post from employee; 注意distinct去重要寫在查詢字段的前面,否則會報錯,關於distinct使用時的其餘問題看下面的總結

  distinct的注意問題

 

  說完去重,咱們看一下order by,排序

七 查詢排序:ORDER BY

  

複製代碼
按單列排序
    SELECT * FROM employee ORDER BY salary; #默認是升序排列
    SELECT * FROM employee ORDER BY salary ASC; #升序
    SELECT * FROM employee ORDER BY salary DESC; #降序

可是你看,若是咱們按照age來排序,你看看是什麼效果:
mysql> SELECT * FROM employee ORDER BY age;
+----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 1 | egon | male | 18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使 | NULL | 7300.33 | 401 | 1 |
| 17 | 程咬銅 | male | 18 | 2015-04-11 | operation | NULL | 18000.00 | 403 | 3 |
| 16 | 程咬銀 | female | 18 | 2013-03-11 | operation | NULL | 19000.00 | 403 | 3 |
| 15 | 程咬金 | male | 18 | 1997-03-12 | operation | NULL | 20000.00 | 403 | 3 |
| 12 | 星星 | female | 18 | 2016-05-13 | sale | NULL | 3000.29 | 402 | 2 |
| 11 | 丁丁 | female | 18 | 2011-03-12 | sale | NULL | 1000.37 | 402 | 2 |
| 18 | 程咬鐵 | female | 18 | 2014-05-12 | operation | NULL | 17000.00 | 403 | 3 |
| 7 | jinxin | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 |
| 6 | jingliyang | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 |
| 13 | 格格 | female | 28 | 2017-01-27 | sale | NULL | 4000.33 | 402 | 2 |
| 14 | 張野 | male | 28 | 2016-03-11 | operation | NULL | 10000.13 | 403 | 3 |
| 5 | liwenzhou | male | 28 | 2012-11-01 | teacher | NULL | 2100.00 | 401 | 1 |
| 10 | 丫丫 | female | 38 | 2010-11-01 | sale | NULL | 2000.35 | 402 | 2 |
| 9 | 歪歪 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 |
| 8 | 成龍 | male | 48 | 2010-11-11 | teacher | NULL | 10000.00 | 401 | 1 |
| 4 | yuanhao | male | 73 | 2014-07-01 | teacher | NULL | 3500.00 | 401 | 1 |
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 3 | wupeiqi | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
+----+------------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+

  發現什麼,按照年齡來升序排的,沒問題,可是你看年齡相同的那些按什麼排的,是否是看着是亂的啊,可是無論它對這種相同數據的內容怎麼排序,咱們是否是想若是出現相同的數據,那麼這些相同的數據也按照一個依據來排列啊:

  因此咱們能夠給相同的這些數據指定一個排序的依據,看下面:
按多列排序:先按照age升序,若是年紀相同,則按照薪資降序
    SELECT * from employee
        ORDER BY age, #注意排序的條件用逗號分隔
        salary DESC;
複製代碼

 

  小練習:

1. 查詢全部員工信息,先按照age升序排序,若是age相同則按照hire_date降序排序
2. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資升序排列
3. 查詢各崗位平均薪資大於10000的崗位名、平均工資,結果按平均薪資降序排列

 

 

複製代碼
#題目1
mysql> select * from employee ORDER BY age asc,hire_date desc;

#題目2 
mysql> select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) asc;
#注意:查詢語句的語法是固定上面這樣寫的,可是運行順序是這樣的:一、from  二、where  三、group by  四、having  五、select  六、distinct 七、order by  八、limit,咱們下面要學的
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| operation |  16800.026000 |
| teacher   | 151842.901429 |
+-----------+---------------+

#題目3
mysql> select post,avg(salary) from employee group by post having avg(salary) > 10000 order by avg(salary) desc;
+-----------+---------------+
| post      | avg(salary)   |
+-----------+---------------+
| teacher   | 151842.901429 |
| operation |  16800.026000 |
+-----------+---------------+
複製代碼

 

八 限制查詢的記錄數:LIMIT

複製代碼
示例:
  #取出工資最高的前三位 SELECT * FROM employee ORDER BY salary DESC LIMIT 3; #默認初始位置爲0,從第一條開始順序取出三條 SELECT * FROM employee ORDER BY salary DESC LIMIT 0,5; #從第0開始,即先查詢出第一條,而後包含這一條在內日後查5條 SELECT * FROM employee ORDER BY salary DESC LIMIT 5,5; #從第5開始,即先查詢出第6條,而後包含這一條在內日後查5條
複製代碼

 

 

  小練習:分頁顯示,每頁顯示5條。咱們工做中常常會涉及到數據分頁顯示,由於數據量很大的時候,加入上10w條數據,咱們是否是要分開給用戶顯示啊,要否則頁面上都顯示不過來,即使是顯示過來了,用戶看着是否是也很不爽啊,要一直往下面滾輪,對不對,用戶體驗很差,因此你會發現有好多的網站均可以看到一個分頁的功能。

複製代碼
mysql> select * from  employee limit 0,5;
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name      | sex  | age | hire_date  | post                                    | post_comment | salary     | office | depart_id |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
|  1 | egon      | male |  18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使              | NULL         |    7300.33 |    401 |         1 |
|  2 | alex      | male |  78 | 2015-03-02 | teacher                                 |              | 1000000.31 |    401 |         1 |
|  3 | wupeiqi   | male |  81 | 2013-03-05 | teacher                                 | NULL         |    8300.00 |    401 |         1 |
|  4 | yuanhao   | male |  73 | 2014-07-01 | teacher                                 | NULL         |    3500.00 |    401 |         1 |
|  5 | liwenzhou | male |  28 | 2012-11-01 | teacher                                 | NULL         |    2100.00 |    401 |         1 |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
5 rows in set (0.00 sec)

mysql> select * from  employee limit 5,5;
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| id | name       | sex    | age | hire_date  | post    | post_comment | salary   | office | depart_id |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
|  6 | jingliyang | female |  18 | 2011-02-11 | teacher | NULL         |  9000.00 |    401 |         1 |
|  7 | jinxin     | male   |  18 | 1900-03-01 | teacher | NULL         | 30000.00 |    401 |         1 |
|  8 | 成龍       | male   |  48 | 2010-11-11 | teacher | NULL         | 10000.00 |    401 |         1 |
|  9 | 歪歪       | female |  48 | 2015-03-11 | sale    | NULL         |  3000.13 |    402 |         2 |
| 10 | 丫丫       | female |  38 | 2010-11-01 | sale    | NULL         |  2000.35 |    402 |         2 |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
5 rows in set (0.00 sec)

mysql> select * from  employee limit 10,5;
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| id | name      | sex    | age | hire_date  | post      | post_comment | salary   | office | depart_id |
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
| 11 | 丁丁      | female |  18 | 2011-03-12 | sale      | NULL         |  1000.37 |    402 |         2 |
| 12 | 星星      | female |  18 | 2016-05-13 | sale      | NULL         |  3000.29 |    402 |         2 |
| 13 | 格格      | female |  28 | 2017-01-27 | sale      | NULL         |  4000.33 |    402 |         2 |
| 14 | 張野      | male   |  28 | 2016-03-11 | operation | NULL         | 10000.13 |    403 |         3 |
| 15 | 程咬金    | male   |  18 | 1997-03-12 | operation | NULL         | 20000.00 |    403 |         3 |
+----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
5 rows in set (0.00 sec)
到最後不夠五條了怎麼辦,徹底不影響,接着寫

  mysql> select * from employee limit 15,5;
  +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
  | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
  +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
  | 16 | 程咬銀 | female | 18 | 2013-03-11 | operation | NULL | 19000.00 | 403 | 3 |
  | 17 | 程咬銅 | male | 18 | 2015-04-11 | operation | NULL | 18000.00 | 403 | 3 |
  | 18 | 程咬鐵 | female | 18 | 2014-05-12 | operation | NULL | 17000.00 | 403 | 3 |
  +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+
  3 rows in set (0.00 sec)

#到目前爲止,單表查詢全部的語法都講完了,語法就是按照咱們博客最上面說的語法順序來寫,可是執行的時候,要按照對應的各個方法的優先級去執行。

 

複製代碼

 

九 使用正則表達式查詢

複製代碼
#以前咱們用like作模糊匹配,只有%和_,侷限性比較強,因此咱們說一個正則,以前咱們是否是學過正則匹配,你以前學的正則表達式均可以用,正則是通用的
SELECT * FROM employee WHERE name REGEXP '^ale'; SELECT * FROM employee WHERE name REGEXP 'on$'; SELECT * FROM employee WHERE name REGEXP 'm{2}'; 小結:對字符串匹配的方式 WHERE name = 'egon'; WHERE name LIKE 'yua%'; WHERE name REGEXP 'on$';
複製代碼

 

  小練習:

查看全部員工中名字是jin開頭,n或者g結果的員工信息
select * from employee where name regexp '^jin.*[g|n]$';
相關文章
相關標籤/搜索