1. 程式人生 > 其它 >MySQL之函式大全

MySQL之函式大全

關於函式的說明

  • 概念:類似python中的方法,將一組邏輯語句封裝在方法體中,對外暴露方法名

  • 好處:

    • 隱藏了實現細節
    • 提高程式碼的重用性
  • 呼叫:select 函式名(實參列表) [from 表]

  • 分類:

    • 單行函式:作用於表中的每一行記錄,一條記錄出來一個結果
      • 字元函式
      • 數學函式
      • 日期函式
      • 其他函式
      • 流程控制函式
    • 聚合函式:作用於一行或者多行,最終返回一個結果,用作統計使用
      • sum 求和
      • avg 平均值
      • max 最大值
      • min 最小值
      • count 計算個數

字元函式

length(str)

  • 獲取引數值的位元組個數
    • 對於utf8字符集來說,一個英文佔1個位元組;一箇中文佔3個位元組
    • 對於gbk字符集來說,一個英文佔1個位元組;一箇中文佔2個位元組

concat(str1,str2,...)

  • 拼接字串

upper(str)

  • 將字元中的所有字母變為大寫

lower(str)

  • 將字元中所有字母變為小

substr(str,start,len)

  • 從start3位置開始擷取字串,len表示要擷取的長度
    • 沒有指定len長度:表示從start開始起,擷取到字串末尾。
    • 指定了len長度:表示從start開始起,擷取len個長度。

instr(str,要查詢的子串)

  • 返回子串第一次出現的索引,如果找不到,返回0
    • 當查詢的子串存在於字串中:返回該子串在字串中【第一次】出現的索引。
    • 當查詢的子串不在字串中:返回0。

trim(str)

  • 去掉字串前後的空格
    • 該函式只能去掉字串前後的空格,不能去掉字串中間的空格。

lpad(str,len,填充字元)

  • 用指定的字元,實現對字串左填充指定長度

rpad(str,len,填充字元)

  • 用指定的字元,實現對字串右填充指定長度

replace(str,子串,另一個字串)

  • 將字串str中的字串,替換為另一個字串

數學函式

round(x,[保留的位數])

  • 四捨五入
    • 當對正數進行四捨五入:按照正常的計算方式,四捨五入即可。
    • 當對負數進行四捨五入:先把符號丟到一邊,對去掉負號後的正數進行四捨五入,完成以後,再把這個負號,補上即可。

ceil(x)

  • 向上取整,返回>=該引數的最小整數,又稱為天花板函式
  • 天花板函式:在excel,python中均存在這個函式。你就想象一下你家的天花板,把這個數字丟到天花板上,求的是大於等於這個數字的最小整數

floor(x)

  • 向下取整,返回<=該引數的最大整數。又稱為地板函式
  • 地板函式:在excel,python中均存在這個函式。你就想象一下你家的地板,把這個數字丟到地板上,求的是小於等於這個數字的最大整數

truncate(x,D)

  • 截斷:也是在excel,python中均存在,含義基本都是一致的。

理解如下:

"參考下面的示例圖,體會如下文字"

  • D是正數,操作的是小數點右側的小數部分。

    • D=1,直接從第1個位置處,砍掉後面的部分。
    • D=2,直接從第2個位置處,砍掉後面的部分。
    • ......
  • D是0,直接去掉小數部分。

  • D是負數,操作的是小數點左側的整數部分。

    • D=-1,直接從-1位置處,先砍掉後面的小數部分,並且"從當前位置起(包括當前位置),後面整數部分替換為0"。
    • D=-2,直接從-2位置處,先砍掉後面的小數部分,並且"從當前位置起(包括當前位置),後面整數部分替換為0"。
    • ……

示例圖:

操作如下:

mod(被除數,除數)

  • 取餘
    • 當被除數為正數,結果就是正數。
    • 當被除數為負數,結果就是負數。

操作如下:

日期時間函式

  • 日期的含義:指的是我們常說的年、月、日。
  • 時間的含義:指的是我們常說的時、分、秒。

在講述下面函式之前,我們先補充一個知識,不同時間格式符表示什麼含義呢?

now()

  • 返回系統當前的日期和時間

操作如下:

curdate()

  • 只返回系統當前的日期,不包含時間

操作如下:

curtime()

  • 只返回系統當前的時間,不包含日期

操作如下:

獲取日期和時間中年、月、日、時、分、秒;

  • 獲取年份:year(),例如:select year(now()),返回系統當前的日期和時間中的年份。
  • 獲取月份:month(),例如:select month(now()),返回系統當前的日期和時間中的月份。
  • 獲取日期:day(),例如:select day(now()),返回系統當前的日期和時間中的日期。
  • 獲取小時:hour(),例如:select hour(now()),返回系統當前的日期和時間中的小時。
  • 獲取分鐘:minute(),例如:select minute(now()),返回系統當前的日期和時間中的分鐘。
  • 獲取秒數:second(),例如:select second(now()),返回系統當前的日期和時間中的秒數。

weekofyear()

  • 獲取當前時刻所屬的週數

操作如下:

quarter()

  • 獲取當前時刻所屬的季度

操作如下:

str_to_date()

  • 將日期格式的字串,轉換成指定格式的日期

操作如下:

date_format()

  • 將日期轉換成日期字串
    • %Y-%m-%d返回的月份是01,02...這樣的格式。
    • %Y-%c-%d返回的月份是1,2...這樣的格式。

操作如下:

date_add() + interval

  • 向前、向後偏移日期和時間

操作如下:

last_day()

  • 提取某個月最後一天的日期

操作如下:

datediff(end_date,start_date)

  • 計算兩個時間相差的天數

操作如下:

timestampdiff(unit,start_date,end_date)

  • 計算兩個時間返回的年/月/天數

  • unit引數是確定(start_date,end_date)結果的單位,表示為整數,以下是有效單位:

    • year:年份
    • month:月份
    • day:天
    • hour:小時
    • minute: 分鐘
    • second:秒
    • microsecond:微秒
    • week:週數
    • quarter:季度

操作如下:

流程控制函式

if函式

  • 實現if-else的效果

ifnull函式

  • 判斷值是否為null,是null用指定值填充

case...when函式的三種用法

case ... when共有三種用法。

有如下資料:

① 等值判斷:類似於java中switch case的效果

-- case ... when用作等值判斷的語法格式
case 要判斷的欄位或表示式
when 常量1 then 要顯示的值1或語句1
when 常量2 then 要顯示的值2或語句2
...
else 要顯示的值n或語句
end

操作如下:

② 區間判斷:類似於python中if-elif-else的效果

-- case ... when用作區間判斷的語法格式
case 
when 條件1 then 要顯示的值1或語句1
when 條件2 then 要顯示的值2或語句2
...
else 要顯示的值n或語句n
end 

操作如下:

③ case ... when和聚合函式聯用

利用上述原始表,完成如下問題:

-- 18、查詢各科成績最高分、最低分和平均分,以如下形式顯示:
-- 課程ID,課程name,最高分,最低分,平均分,及格率,中等率,優良率,優秀率
-- 及格為:>=60,中等為:70-80,優良為:80-90,優秀為:>=90

操作如下:

select sc.c,cname,
max(score) 最高分,min(score) 最低分,avg(score) 平均分,
sum(case when score>60 then 1 else 0 end)/count(*) 及格率,
sum(case when score>=70 and score<80 then 1 else 0 end)/count(*) 中等率,
sum(case when score>=80 and score<90 then 1 else 0 end)/count(*) 優良率,
sum(case when score>=90 then 1 else 0 end)/count(*) 優秀率
from sc left join course 
on sc.c = course.c
group by sc.c;

結果如下:

測試資料:

-- 建表語句
create table test(
id int primary key auto_increment,
name varchar(20) not null,
sal int,
birth date)charset=utf8;

-- 插入資料
insert into test(name,sal,birth) values 
("pure",6500,'1996.11.20'),
("Hobby",4000,'1997.6.10'),
("Aline",5500,'2000.5.1'),
("Bob",10000,'2008.10.1');

聚合函式的簡單使用

select * from test;

select count(*) 統計行數,
sum(sal) 求和, avg(sal) 平均值,
max(sal) 最大值, min(sal) 最小值
from test;

執行結果:

聚合函式中傳入的引數,所支援的資料型別

mysql不是強型別的程式語言。也就是說,有些語句執行結果可能不報錯,但是執行結果無實際意義,因此,我們也認為是不正確的。

sum()和avg()

結論如下:

  • sum()函式和avg()函式對於字串型別、日期/時間型別的計算都沒有太大意義。因此,sum()函式和avg()函式,我們只用來對小數型別和整型進行求和。

max()和min()

結論如下:

  • max()min()中傳入的是"整型/小數型別",計算的是數值的最大值最小值

  • max()min()中傳入的是"日期型別",max()計算的最大值是離我們最近的那個日期,min()計算的最小值是離我們最遠的那個日期

  • max()min()中傳入的是字串型別max()計算的最大值是按照英文字母順序顯示的,min()計算的最小值也是按照英文字母順序顯示的,意義不太大

count()

插入一條資料

insert into test(name) values('LiLei');

結論如下:

  • count()函式可以傳入任何資料型別,表示對行計數。

  • 但是下面的知識點需要特別注意的

  • 首先看看count(sal),count(birth)這兩句表示的是什麼意思?這兩句分別表示的是
    對sal列欄位、birth列欄位的行數,進行統計。由於其中有一條記錄是null值,因此使用count()
    函式計數的時候,會忽略掉null行。

  • 其次,對於count(\*)表示的是統計【整個表】有多少行,這個肯定是對原始資料的行數的正確
    統計,只要整張表某一行有一個列欄位的值不是nullcount(\*)就會認為該行為1行。當然要是一
    整行都是null值,你也沒必要插入這條記錄。

總結:當某個欄位列中沒有null值,則count(列欄位)=count(*)
當某個欄位列中有null值,則count(列欄位)<count(*)。 因此,假如你想統計的是整張表的行數,請用count(*)

其實所有的分組函式都忽略null值的,但上面那個count()函式碰到null值要特別注意。

結論如下:

  • 對於avg(sal)求平均值來說,(6500+4000+5500+10000)/4=6500。對於後面這個
    sum()/count(*)求平均值來說,(6500+4000+5500+10000)/5=5200。
  • 好好體會上述例子,有時候某人成績雖然記錄的是null,但是你仍然有5個人存在,所
    以你要考慮一下怎麼使用合適的函式,達到你想要的結果。

count(1),count(0),count(*),count(列名)的區別

count(0),count(1),count(*)不會過濾空值

count(列名)會過濾空值

無論是sum(1),sum(0),count(1),count(0),avg(1),avg(0),原理都是一樣的,
相當於在原表中新增一列。

其次,我們知道where後面接的是邏輯值,當使用where 1where 0原理也還是
一樣,也相當於在原表中新增一列。

我們只需要記住在mysql中:非0即為true,0為false。也就是說,下面的所有是
1的地方,你可以換成任何非0數字,都是可以的。

count(1),count(0)原理圖如下:

測試結果:

count(*),count(1)計數的效率問題

  • MYISAM儲存引擎下,count(*)的效率高。
  • INNODB儲存引擎下,count(*)和count(1)的效率差不多,比count(欄位)效率要高一些。
  • 綜上所述:優先使用count(*)。

聚合函式和group by的聯合使用

關於這個知識點,我們將會在後面的知識點中進行講述。在這裡我們只需要記住一句話:當SQL語句中使用了group by分組函式後,select後面的欄位必須是group by後面的欄位 + 聚合函式的使用。

其它常用系統函式