文章目錄
說明
一些說明
本文中所有中括號擴起的文字均代表可以替換的文字(包括中括號本身)
例如在我博客中的:
select [字段1],[字段2],...,[字段n] from [表名] where [查詢條件];
在實際使用時,可以寫作:
select name,age from users where id=3;
表結構
users表
工號 | 姓名 | 性別 | 年齡 | 職位 | 辦公電話 | 手機號 |
---|---|---|---|---|---|---|
201215121 | 李勇 | 男 | 40 | 主管 | 13650 | 13365245865 |
201215122 | 劉晨 | 女 | 29 | 收銀員 | 13622 | 12535468521 |
201215123 | 王敏 | 女 | 29 | 會計 | (Null) | 17685324586 |
201215124 | 劉柳 | 男 | 42 | 總監 | 13623 | 19658245753 |
201215125 | 王輝 | 妖 | 29 | 會計 | (Null) | 16698532547 |
如上users表所示,
- users叫做表名
- “工號”、“姓名”、“性別”、“年齡”和“職位”等叫做一個字段
- 該表的一行(例如:201215122 劉晨 女 29 收銀員 13622 12535468521)叫做一個記錄
1. 基本查詢操作
1.1. 基本語法
表的查詢,即查詢表中的數據記錄,表的查詢操作是SQL的基本數據操作之一,也是使用頻率最高、最重要的數據操作。
一個一般的查詢語法如下:
select [字段1],[字段2],...,[字段n] from [表名] where [查詢條件];
關鍵字解釋:
select: 查詢語句的起始關鍵字,表示該操作爲查詢操作
from: 後接數據源,表示在[表名]中查詢[字段i]
where: 後接查詢條件,表示要對查詢做的限制,該操作可以幫助數據庫使用者做精確的查找
1.2. * 查詢所有數據
查詢所有字段會把表內所有的數據都查詢出來,在select語句中使用星號" * "通配符來查詢表中的所有字段
語法爲:
select * from [表名];
例如:
select * from users; --表示從users表中查詢所有字段,
查詢結果爲:
1.3. as 給字段取別名
給字段取別名的意義在於可以清晰的展示某一字段所表示的內容,例如表中有一列“月工資”,要計算“年工資”時可將月工資12,這時候sql會顯示該字段的字段名爲“月工資12”,這對查詢結果的展示很不友好,通常情況下都會給它取一個別名。
取表名的可以使用“as”關鍵字,或者直接在字段後面接“"[別名]"”
語法爲:
select [字段名] as "[別名]", [字段名]"[別名]" from users;
例如下例:
select 工號, 工號 as "工", 姓名, 姓名"姓" from users;
1.4. distinct 消除重複
如果查詢結果中出現重複數據,可用關鍵字“distinct”消除,若沒有加上“distinct”關鍵字,查詢結果將默認展示重複數據。
需要注意的是,“distinct”關鍵字是作用於所有字段的組合,只有在所有字段值都重複的情況下,纔會消除重複。
語法如下:
select distinct [字段1],[字段2],...,[字段n] from [表名]
例如:
select 姓名,性別,年齡,職位 from users;
select distinct 姓名,性別,年齡,職位 from users;
左邊是未加distinct關鍵字的查詢結果,右邊是加上distinct關鍵字的查詢結果
1.4. 運算符
SQL提供的基本算術運算符有:
+ :加法
- :減法
* :乘法
/ :除法
% :取餘
SQL的算術運算符可以在列、常量之間運算,例如:
select 姓名, 年齡, 年齡+2, 年齡*2, 年齡*2, 年齡/2, 年齡%2 from users;
查詢結果爲:
要注意的是,運算符也是有優先級的,優先級規則與我們的數學運算符號規則一致。
2. where 條件查詢
在select語句中,可以通過where子句,對數據進行過濾,其語法格式爲
select [字段1],[字段2],...,[字段n] from [表名] where [查詢條件];
例如:
-- 篩選出年齡大於30的人
select 姓名, 年齡 from users where 年齡 > 30;
2.1. where中的比較運算符
比較運算符 | 作用 | |||
---|---|---|---|---|
= | 等於 | <> | 不等於 | |
> | 大於 | < | 小於 | |
>= | 大於等於 | <= | 小於等於 | |
between [值1] and [值2] | 介於[值1]和[值2]之間 | in([值1], [值2],…, [值n]) | 包含在[值1], [值2],…, [值n]之中 | |
like | 條件匹配(%:匹配多個字符,_:匹配一個字符) | [值] is null | 判斷[值]是否爲空 |
例如:
-- 查詢年齡不等於40的人
select 姓名, 年齡 from users where 年齡 <> 40;
-- 查詢年齡介於20到30之間的人
select 姓名, 年齡 from users where 年齡 between 20 and 30;
-- 匹配姓名中第一個字是‘劉’,第二個字隨意的人
select 姓名 from users where 姓名 like '劉_';
2.2. where中的邏輯運算符
邏輯運算符 | 作用 |
---|---|
[表達式1] and [表達式2] | 兩個表達式都爲true,才返回true ,否則返回false |
[表達式1] or [表達式2] | 兩個表達式其中之一爲true,就返回true,兩個都爲false,才返回false |
not [表達式] | 若表達式爲true,則返回false,若表達式爲false,則返回true |
例如:
-- 找出年齡大於30的男性
select 姓名, 年齡, 性別 from users where 性別='男' or 年齡>30;
2.3. 排序
對查詢結果進行排序使用order by 關鍵詞
語法:
select [字段1], [字段2],..., [字段n]
from [表名]
order by [字段名1] [排序方式], [字段名2], [排序方式],..., [字段名n] [排序方式];
排序方式有兩種:
- asc 順序排列 (從小到大)
- desc 逆向排列 (從大到小)
例如:
-- 先按年齡順序排列,再將重複值按照工號逆序排列
select 工號, 姓名, 年齡 from users order by 年齡 asc, 工號 desc;
3. 常用函數
3.1. 字符串函數
函數 | 功能 |
---|---|
concat([字符串1],[字符串2],…,[字符串n]) | 連接字符串 |
group_concat([字段]) | 對分組後的字段進行連接 |
insert([字符串1], [下標], [個數], [字符串2]) | 將[字符串1]中從[下標]開始的[個數]個字符替換爲[字符串2] |
lower([字符串]) | 將[字符串]中的字母轉換爲小寫 |
upper([字符串]) | 將[字符串]中的字母轉換爲大寫 |
length([字符串]) | 計算[字符串]的字節長度 |
char_length([字符串]) | 計算[字符串]的字符長度 |
lpad([字符串1], [長度], [字符串2]) | 在[字符串1]的左邊填充[字符串2],使字符串長度達到[長度] |
rpad([字符串1], [長度], [字符串2]) | 在[字符串1]的右邊填充[字符串2],使字符串長度達到[長度] |
trim([字符串]) | 去掉[字符串]首尾的空格 |
repeat([字符串],[次數]) | 將[字符串]重複[次數]次 |
replace([字符串1], [字符串2], [字符串3]) | 用[字符串3]替換[字符串1]中所有的[字符串2] |
substring([字符串], [下標], [長度]) | 返回[字符串1]中從[下標]位置其長度爲[長度]的子串 |
舉例:
-- concat(工號,姓名)連接字段`工號`和`姓名`
select 工號, 姓名, concat(工號,姓名) from users;
--lpad(姓名, 5, 'X')在姓名字段的左邊填充字符'L',使其字符長度達到5
--rpad(姓名, 5, 'X')在姓名字段的右邊填充字符'R',使其字符長度達到5
select lpad(姓名, 5, 'L'),rpad(姓名, 5, 'R') from users;
3.2. 數值函數
函數 | 功能 |
---|---|
abs([數值]) | 返回[數值]的絕對值 |
ceil([數值]) | 返回不小於[數值]的最小整數值 |
floor([數值]) | 返回不大於[數值]的最小整數值 |
mod([數值1], [數值2]) | 返回[數值1]/[數值2]的模 |
rand() | 返回一個0~1之間的隨機數 |
round([數值1], [數值2]) | 返回[數值1]四捨五入後保留[數值2]位小數的值 |
truncate([數值1], [數值2]) | 返回[數值1]截斷後保留[數值2]位小數的值 |
例如:
-- 返回不小於0.8、-0.8和不大於0.8、-0.8的數值
select ceil(0.8), ceil(-0.8), floor(0.8), floor(-0.8) from users;
-- round(3.14159,3)返回3.14159四捨五入後保留3位小數的值
-- truncate(3.14159,3)返回3.14159截斷後保留3位小數的值
select round(3.14159,3), truncate(3.14159,3) from users;
3.3. 日期和時間函數
函數 | 功能 |
---|---|
curdate() | 返回當前日期 |
curtime() | 返回當前時間 |
now() | 返回當前的日期和時間 |
year([日期]) | 計算[日期]的年份 |
monthname([日期]) | 計算[日期]的月份,並返回其英文名 |
week([日期]) | 計算[日期]爲一年中的第幾周 |
hour([時間]) | 計算[時間]的小時值 |
minute([時間]) | 計算[時間]的分鐘值 |
date_format([日期],[格式]) | 將[日期]按[格式]返回 |
date_add([日期或時間],interval [時間間隔] [間隔類型]) | 返回一個[日期或時間]後接一個[時間間隔]的時間值 |
datediff([時間1],[時間2]) | 計算[時間1]和時間[2]之間的間隔天數 |
例如:
select now(),
year(now()), monthname(now()), week(now()),
hour(now()), minute(now());
3.3.1. date_format()函數
格式 | 描述 | 格式 | 描述 | |
---|---|---|---|---|
%M | 英文月名 | %j | 該日期所在一年中的第幾天(000-366) | |
%b | 英文月名縮寫 | %D | 該日期所在一月中的第幾天(帶次序1st,2nd,…,31th) | |
%c | 月數(0-12) | %e | 該日期所在一月中的第幾天(0-31) | |
%m | 月數(01-12) | %d | 該日期所在一月中的第幾天(00-31) | |
%k | 該時間所在的小時(0-23) | %i | 該時間所在一小時中的分鐘數(00-59) | |
%H | 該時間所在的小時(00-23) | %f | 該時間所在一秒中的微秒數 | |
%h | 該時間所在一天中的小時(01-12) | %a | 該時間所在的星期名的英文縮寫 | |
%I | 該時間所在一天中的小時(01-12),同%h |
例如:
select now(), date_format(now(), '%M %m %D');
3.3.2. date_add()函數
間隔類型 | 描述 | 間隔類型 | 描述 | |
---|---|---|---|---|
microsecond | 微秒 | second | 秒 | |
minute | 分鐘 | hour | 小時 | |
day | 天 | week | 星期 | |
month | 月 | quarter | 季度(一個季度三個月) | |
year | 年 | second_microsecond | 秒+微秒(寫成浮點數形式 例如10.1表示間隔10秒加1微秒) |
|
minute_microsecond | 分+微秒 | minute_second | 分+秒 | |
hour_microsecond | 小時+微秒 | hour_second | 小時+秒 |
例如:
-- 間隔一個季度
select now(), date_add(now(), interval 1 quarter);
-- 間隔1分2秒
select now(), date_add(now(), interval 1.2 minute_second);
3.4. 流程控制函數
3.4.1. if 流程函數
根據表達式的真假值做出判斷。
語法:
-- 如果[表達式]爲真,則返回[true返回值],否則返回[false返回值]
if ([表達式], [true返回值], [false返回值]);
例如:
-- 若字段值爲‘劉晨’,則返回‘是’,否則返回‘否’
select 姓名, if(姓名='劉晨', '是', '否') from users;
3.4.2. ifnull 流程函數
ifnull用於判斷表達式是否爲空。
語法:
-- 若[表達式1]不爲null,就返回[表達式1]的值,若[表達式1]爲null,就返回[表達式2]的值
ifnull([表達式1], [表達式2])
例如:
-- (左圖) 查詢某單位人員的聯繫方式,有些人沒有辦公電話,只有手機號,這時會出現信息冗餘
select 姓名, 辦公電話, 手機號 from users
-- (右圖) 若使用ifnull()函數來處理,可以消除這些信息冗餘
-- ifnull(辦公電話, 手機號) 若有辦公電話,則顯示辦公電話,若沒有辦公電話,就用手機號代替
select 姓名, ifnull(辦公電話, 手機號) from users
3.4.3. case 流程函數
case流程函數可以幫助數據庫使用人員根據情況從多個選項中作出選擇。
語法:
-- case表達式可以根據[表達式1]的結果[值1]、[值2]、...、[值n]
-- 返回相應的[返回值1]、[返回值2]、...、[返回值n]
-- 如果[表達式1]的結果不在[值1]、[值2]、...、[值n]中,則返回[默認返回值]
case [表達式1]
when [值1] then [返回值1]
when [值2] then [返回值2]
...
when [值n] then [返回值n]
else [默認返回值]
end
例如:
-- 用case表達式對性別進行中英文轉換
select 姓名, 性別,
case 性別
when '男' then 'male'
when '女' then 'female'
else 'unknown'
end
from users
3.5. 聚合函數
聚合函數用於對一組數進行運算,然後返回一個結果,需要注意的是,除了count()以外,其他的聚合函數在計算時會忽略null值。
常用的聚合函數有:
聚合函數 | 作用 |
---|---|
count([列名]) | 計算某一列有多少行 |
avg([列名]) | 計算某一列數值的平均值 |
sum([列名]) | 計算某一列數值的和 |
max([列名]) | 求出某一列的最大值 |
min([列名]) | 求出某一列的最小值 |
例如:
select count(*), avg(年齡), sum(年齡), max(年齡), min(年齡) from users
3.6. 數據庫屬性函數
屬性函數 | 功能 |
---|---|
database() | 返回當前數據庫名 |
version() | 返回當前數據庫版本 |
user() | 返回當前登錄用戶的用戶名 |
inet_aton([IP地址]) | 返回IP地址的數字表示 |
inet_ntoa([IP數]) | 將IP的數字表示轉換爲IP地址 |
password([密碼]) | 返回加密後的[密碼] |
md5([字符串]) | 返回[字符串]的MD5值(32位的16進制串) |
例如:
-- IP地址'192.168.1.1'與其數字表示的相互轉換
select inet_aton('192.168.1.1'), inet_ntoa(3232235777);
4. group by 分組查詢
分組查詢可以將值相同的字段分在同一個組,常和各種函數一起使用。關鍵詞是group by,寫在where子句之後。
如果要對分組後的結果進行條件過濾,要使用having關鍵字,having就是group by中的where,但是having子句中可以使用聚合函數,where中不行。
語法:
select [字段],[函數1],[函數2],...,[函數n]
from [表名]
group by [字段]
having [表達式];
需要注意的是,select中兩個的[字段]必須相同,因爲對數據按[字段]進行分組以後,其他的字段都會被打亂,無法直接查詢出來。
例如:
-- (右圖)對分組後的姓名字段值進行連接,並統計每一個分組的年齡總和
select 年齡, group_concat(姓名), sum(年齡) from users group by 年齡;
-- 帶having子句的分組查詢
-- 首先對分組後的姓名字段值進行連接,並統計每一個分組的年齡總和
-- 然後從中選出年齡小於30的分組,返回
select 年齡, group_concat(姓名), sum(年齡)
from users
group by 年齡
having 年齡 < 30;