經過寫SQL查詢,咱們能夠發現不少簡單查詢語句主要就是由一些算術操做、字段操做、函數還有各類子句構成的,今天咱們從這個角度對MySQL單表查詢的基礎知識進行一個彙總。正則表達式
以這份模擬薪酬統計表爲例算法
字段解讀:
id(工號),name(員工姓名),dep(部門),post(職位),years(工做年限),sal(薪酬),bon(獎金)數據庫
計算部分數組
1.計算字段說明函數
不少時候,存在數據庫表中的數據不是咱們直接須要的,要進行一些計算、清洗或者格式化等操做,因此就有了計算字段的存在,它們不實際存在於數據庫表中,是運行時在select語句中建立的。post
2.算術操做符3d
算術操做符:+ 加法,- 減法,* 乘法,/(DIV) 除法,%(MOD) 求餘code
3.算術計算regexp
# 統計一下CFO的年薪 select name, sal*12+bon from eg where post = 'cfo';
4.字段拼接及列別名orm
列別名: 別名是一個字段或者值的替換名,能夠用關鍵字AS賦予(也能夠省略掉AS)。
在上面的例子中,若是要對計算後的年薪賦予一個名稱,修改第一行代碼便可
select name, sal*12+bon as '年薪'
下面咱們看下使用concat() 函數來進行字段拼接
# 將員工職位標註在員工名後面
select concat(name, post)
from eg;
5.格式化顯示
上面例子是字段的拼接,可是顯然看起來不方便,因此咱們進一步看看如何進行格式化顯示,假如咱們如今須要讓每一個員工的崗位、年薪顯示在一塊兒,構成一個「員工信息」字段
select concat('姓名:', name, '\t', '(', '崗位:', post, '\t', '年薪:', sal*12, ')') as '員工信息'
from eg;
#這裏由於有些員工獎金爲null,沒法有效參與計算,因此年薪的算法一概去掉獎金部分
函數部分
1.經常使用統計函數
count():返回某列的行數
avg():返回某列的平均值
sum():返回某列值的和
max():返回某列最大值
min():返回某列最小值
咱們先看下這些函數的簡單應用,後面子句中還會提到
select count(id) from eg;
select avg(sal) from eg;
select sum(sal) from eg;
select max(sal) from eg;
select min(sal) from eg;
經過上面的統計數據,咱們就能夠對這個15人團隊的總體人力成本有一個大體瞭解
2.文本處理函數
left():返回串左邊的字符
length():返回串的長度
locate():找出串的一個子串
lower():將串轉換爲小寫
ltrim():去掉串左邊的空格
right():返回串右邊的字符
rtrim():去掉串右邊的字符
soundex():返回串的soundex值
substring():返回子串的字符
upper():將串轉換爲大寫
3.時間日期函數
adddate():增長一個日期(天、周等)
addtime():增長一個時間(時、分等)
curdate():返回當前日期
curtime():返回當前時間
date():返回日期時間的日期部分
datediff():計算兩個日期之差
date_add():高度靈活的日期運算函數
date_format():返回一個格式化的日期或時間串
day():返回一個日期的天數部分
dayofweek():對於一個日期,返回對應的星期幾
hour():返回一個時間的小時部分
minute():返回一個時間的分鐘部分
month():返回一個日期的月份部分
now():返回當前日期和時間
second():返回一個時間的秒部分
time():返回一個日期時間的時間部分
year():返回一個日期的年份部分
4.數值處理函數
abs():返回一個數的絕對值
cos():返回一個角度的餘弦
exp():返回一個數的指數值
mod():返回除操做的餘數
pi():返回圓周率
rand():返回一個隨機數
sin():返回一個角度的正弦
sqrt():返回一個數的平方根
tan():返回一個角度的正切
--《MySQL必知必會》
上面是從《MySQL必知必會》裏直接摘錄的一些經常使用函數,咱們在這裏進行一下彙總,須要的時候能夠方便地參考,就不一一舉例說明了。
子句部分
1.MySQL語法順序
select-->from-->where-->group by-->having-->order by-->limit.
2.MySQL執行順序
from --> where --> group by --> having --> select --> distinct --> order by --> limit.
3.排序
查詢到的數據通常是以在底層表中出現的順序顯示的,若是咱們有排序需求,則不能以此爲依賴,而是要嚴謹地使用order by子句來明確控制。
# 按照員工工齡進行排序
select name, years
from eg
order by years;
![](https://img2020.cnblogs.com/other/1774629/202004/1774629-20200421171010999-313718117.png)
上面的操做查詢了員工姓名與工齡,並按照工齡進行排序,若是須要讓工齡越久的越靠前,咱們就能夠指定一下排序方向
select name, years
from eg
order by years desc;
# asc(升序)/ desc(降序),默認是升序
下面咱們看下如何對多個列進行排序
select name, years, sal, bon from eg order by years asc, sal desc;
這裏要注意,多列排序時,當前一列中有相同行時,纔對相同行按照下一列的規則繼續啓動排序。
4.過濾
工做用的數據庫表中通常包含大量數據,不多會一次所有查詢,因此會使用where子句加過濾條件來查詢咱們須要的數據。
認識操做符
=(等於),<>、!=(不等於),<(小於),<=(小於等於),>=(大於等於),>(大於),between(在指定兩個值之間)
and(邏輯與),or(邏輯或),in(指定條件範圍),not(邏輯非)
like,regexp
單條件匹配
select name from eg where years > 3;
select name, years from eg where years != 1; # 不匹配查詢
select name from eg where bon is null; # 空值查詢
多條件匹配
select name, post, sal from eg where post='clerk' and sal>10000;
select name, years from eg where sal between 10000 and 20000; # 範圍值查詢
select name, years from eg where years not in (1, 3, 5); # 指定條件範圍,並進行非範圍篩選
搜索模式
前面提到的匹配方式都是針對已知值,可是實際狀況中並不老是這樣,有時候咱們須要匹配一些字面值,可是咱們可能並不清楚她們的全貌,這裏就須要用到搜索模式,先認識下簡單的通配符:%(任何字符出現任意次數),_(匹配單個字符),這裏咱們會用到like和regexp兩種操做符,一塊兒來看下。
select name from eg where name like 'a%'; # 查詢姓名以a開頭的員工
![](https://img2020.cnblogs.com/other/1774629/202004/1774629-20200421171013371-640179622.png) select name from eg where name like '_a%'; # 查詢姓名第二個字母爲a的員工 ![](https://img2020.cnblogs.com/other/1774629/202004/1774629-20200421171013576-1635929560.png) select name from eg where name like 'an'; select name from eg where name regexp 'an'; ![](https://img2020.cnblogs.com/other/1774629/202004/1774629-20200421171013840-1064564701.png) 關於regexp的用法這裏會涉及到正則表達式,由於正則的內容還比較多,這篇文章裏咱們只先作一個簡單瞭解,後面會在另外一個專題來講明,這裏咱們注意一下regexp和like的一些使用區別就好,經過上面的例子咱們能夠看到like匹配的是整個列值,因此當'an'只在列值中出現時,like是不會返回對應值的,而regexp操做時只要被匹配的文本在列值裏出現了,那麼相應值就會被返回。
5.分組
經過group by子句能夠對數據進行分組,常常會和統計函數一塊兒使用,接下來咱們看下它們的具體用法。
基本分組
select dep, count(*) as num
from eg
group by dep; # 建立分組並按照部門統計人數
分組排序
select years,avg(sal) as avg_sal from eg group by years order by avg_sal desc; # 按工齡分組並分別計算平均薪資
多字段分組
select dep, years, avg(sal) as dep_year_avg
from eg
group by dep, years; # 先按照部門,再按照工齡進行分組
6.分組過濾
若是咱們要針對分組進行過濾,按照以前的邏輯就應該在分組後面再加上一個過濾條件,這裏須要記住,group by子句後面是不能夠再使用where的,這裏就引出了having子句,能夠用having來篩選成組後的數據。
分組過濾
select dep, count(*) as num
from eg
group by dep
having num > 5; # 查詢人數大於5的部門
where和having的一些使用區別
1.where是在數據分組前進行過濾,having是在數據分組後進行過濾;
2.having可使用字段別名,where不能夠;
3.where是直接從數據表中篩選字段,having是從select查詢的字段中再進行篩選,因此having後面跟的字段必定要在前面已經出現過;
4.having可使用統計函數,where不能夠;
5.group by 子句後面只能用having,不能用where;
7.去重
有時候,咱們只想知道想要的數據都有些什麼不一樣類別,而不是所有取出它們,這個時候就須要使用關鍵字distinct對查詢到的數據進行去重處理
select distinct dep from eg; # 查詢共有多少部門
這裏須要注意的是,進行去重操做時,distinct必須在全部字段的最前面,而且它應用於全部字段而不只是前置它的字段,也就是說若是distinct後面有多個字段,只有它們組合起來的值是相等的纔會被去重,看下面例子
select distinct dep, post from eg;
不過,當統計函數做爲計算字段出現時,distinct能夠和統計函數組合使用,就不必定要放在列的最前面了,舉個以前練習中遇到的例子,下面語句中distinct的用法也是OK的
select activity_date as day, count(distinct user_id) as active_users
8.限制
經過條件查詢有時候符合需求的數據記錄會太多,這時能夠經過limit來限制數量
select name, post
from eg
where post = 'clerk'
limit 3; # 這裏指返回不超過3行的數據
咱們也能夠本身定義偏移量,也就是讓它從咱們想要的行數開始返回
select name, post
from eg
where post = 'clerk'
limit 3, 3;
不過這裏須要注意,在查詢時行數是從0算起的,因此 limit3, 3 指的是從第四行開始返回3行數據,爲了更加清晰,MySQL5還支持另外一種替代語法,以下所示
select name, post
from eg
where post = 'clerk'
limit 3 offset 3;
(不過,我我的以爲前面第一種仍是挺順眼的,後面這個反倒看着懵,哈哈哈哈哈~)
若是limit限制的數量大於所有數量的話,也不會報錯,會返回所有結果,以下
select name, years
from eg
where years > 5
limit 3;
公衆號【DT派】-- 一直在路上,成爲更好的人~