python--MySQl單表查詢

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

複製代碼
from
where
group by
having  # 使用是要放在group by 後面並且前面必須有group by
select
distinct  # 去重 要放在字段的前面,並且字段只能有一個
order by  # 排序,默認升序, order by desc 是降序
limit  #  後面寫多少就顯示多少條數

關鍵字執行優先級
複製代碼

二 .  簡單查詢

複製代碼
#咱們來建立一個員工表,而後對員工表進行一個簡單的查詢,來看一下效果,下面是員工表的字段
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
複製代碼

  查詢操做mysql

複製代碼
簡單查詢
    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   |
    ...
    +--------------+
複製代碼

三 . where約束

  where語句中可使用:正則表達式

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

    1. 比較運算符:> < >= <= <> !=
    2. between 80 and 100 值在80到100之間
    3. in(80,90,100) 值是80或90或100
    4. like 'egon%'
      pattern能夠是%或_,
      %表示任意多字符
      _表示一個字符 
    5. 邏輯運算符:在多個條件直接可使用邏輯運算符 and or notwindows

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

  練習題函數

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

四 . 分組查詢

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

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

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

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

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

  1 group bypost

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

  2 聚合函數測試

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

示例:
    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;
複製代碼

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

#2. Having發生在分組group by以後,於是Having中可使用分組的字段,沒法直接取到其餘字段,having是可使用聚合函數

  having簡單測試spa

複製代碼
#來個需求:統計各部門年齡在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 |
  +---------+-------------------+
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後面運行
複製代碼

  練習題code

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

  distinct : 去重

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

  distinct的注意問題

六 . 查詢排序:order by

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

按多列排序:先按照age升序,若是年紀相同,則按照薪資降序
    SELECT * from employee
        ORDER BY age, #注意排序的條件用逗號分隔
        salary DESC;
複製代碼

  練習題

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

七 . 限制查詢的記錄數: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條剩多少顯示多少
複製代碼

八 . 使用正則表達式查詢

複製代碼
#以前咱們用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$';
複製代碼
相關文章
相關標籤/搜索