- 本博客是《MySQL基礎》系列博客的第七部分,主要介紹MySQL語句中的DQL語句,即我們常說的查詢語句的基本用法,包括簡單的單表查詢、去重、排序、分組查詢、統計查詢、多表查詢、連接查詢、子查詢和聯合查詢
- 本博客既爲方便自己查看複習而作,亦爲你而作,望能有所裨益
- 學習交流請聯繫 [email protected]
DQL簡介
DQL,即Data Definition Language,數據查詢語言,用於數據庫、數據表等數據的查詢,也就是我們常說的增刪改查中的查。
DQL用法
示例數據庫
爲了後續介紹方便,我們使用MySQL自帶的數據庫 Sakila :
此外,在使用數據庫前,我們需要對數據庫有一個基本的瞭解,如果一個一個表打開看顯然不太合適,這時候就需要有一個全局視圖來幫助我們。而MySQL確實也提供了這樣的功能:
- 首次打開時需要自行找到示例數據庫所在地,默認存放在MySQL文件夾下的Samples and Examples文件夾內,以.mwb爲後綴名
- 打開後是這樣的畫面:
- 進而瞭解到該數據庫處理的是租賃事務,其中有顧客數據,有商家數據以及租賃商品的數據。
下面我們就開始學習SQL語句的重頭戲——查詢語句SELECT
的用法吧。
簡單的單表查詢
/* 簡單的表查詢*/
select * from <數據庫>.<數據表>; -- 查詢某一數據庫中某表的全部信息
select <字段名> from <數據庫>.<數據表>; -- 查詢某表的某些字段
select actor_id,first_name from actor;
-- 查詢actor表中actor_id和first_name兩個字段
select <字段名> from <數據庫>.<數據表> where <條件>; -- 條件查詢
select actor_id,first_name from actor where actor_id > 10;
-- 查詢actor表中actor_id和first_name兩個字段中actor_id大於10的字段
select actor_id,first_name from actor where actor_id != 10;
-- 查詢actor表中actor_id和first_name兩個字段中actor_id不等於10的字段
select actor_id,first_name from actor where actor_id between 10 and 20;
-- -- 查詢actor表中actor_id和first_name兩個字段中actor_id位於[10,20]區間內的字段
select actor_id,first_name from actor where actor_id in (10,13,29);
-- 查詢actor表中actor_id和first_name兩個字段中actor_id爲10,13和29的字段
select actor_id,first_name from actor where actor_id not in (10,13,29);
-- 查詢actor表中actor_id和first_name兩個字段中actor_id不爲10,13和29的字段
-- 通配符的使用
select actor_id,first_name from actor where first_name like 'j%';
/* 查詢actor表中actor_id和first_name兩個字段中first_name
爲以j開頭,後跟任意個字符的字段 */
select actor_id,first_name from actor where first_name like 'j__';
/* 查詢actor表中actor_id和first_name兩個字段中first_name
爲以j開頭長度爲3個字符的字段,一個_代表一個字符 */
select actor_id,first_name from actor where first_name not like 'j%';
/* 查詢actor表中actor_id和first_name兩個字段中first_name
不以j開頭,後跟任意個字符的字段 */
select actor_id,first_name from actor where first_name like 'j%' and last_name like '%s';
/* 查詢actor表中actor_id和first_name兩個字段中first_name
爲以j開頭且last_name爲以s結尾的字段 */
select actor_id,first_name from actor where first_name like 'j%' or last_name like '%s';
/* 查詢actor表中actor_id和first_name兩個字段中first_name
爲以j開頭或last_name爲以s結尾的字段 */
去重
-- 去重(distinct)
-- 原始數據中不可避免地存在重複數據,因此在分析數據前要對數據進行去重
select distinct <字段名> from <數據庫>.<數據表>;
select first_name from actor; -- 返回200個名字
select distinct first_name from actor; -- 去重後返回128個名字
select first_name,last_name from actor; -- 返回200個姓名
select distinct first_name,last_name from actor; -- 去重後返回199個姓名
排序
-- 排序
-- 數據庫中記錄的默認排序爲升序
select <字段名> from <數據庫>.<數據表> order by <字段名> [desc];
-- desc爲降序,添加則將該關鍵詞前面的字段降序排列後返回查詢結果
select actor_id,first_name from actor order by actor_id desc;
-- 按actor_id降序排列後返回查詢結果
select actor_id,first_name from actor order by actor_id desc, first_name;
-- 先按演員號降序排列,再按演員名升序排列(字段爲字符串時排序效果不明顯)
select actor_id,first_name from actor order by actor_id desc, first_name desc;
-- 先按演員號降序排列,再按演員名降序排列
分組查詢
-- 分組查詢
-- 數據量較大時,通常對數據進行分組,以瞭解數據的大致情況
select <字段名> from <數據庫>.<數據表> group by <分組字段名>;
select * from film group by rating;
-- 將rating分組後再查看所有數據
select rating,group_concat(film_id) from film group by rating;
-- 查看每個等級對應的記錄編號,concat表示合併多個數組或字符串
select rating,count(film_id) from film group by rating;
-- 查看每個等級對應的記錄數
select rating,count(film_id) from film group by rating with rollup;
-- 查看每個等級對應的記錄數併合計
-- 在分組查詢的基礎上進行條件查詢
select <字段名> from <數據庫>.<數據表> group by <分組字段名> having <條件>;
select rating,count(film_id) from film group by rating having count(film_id) > 200; -- 查詢電影數目大於200的某一等級及該等級的電影數
-- 在分組查詢的基礎上進行排序查詢
select rating,count(film_id),rental_duration from film group by rating,rental_duration order by rating;
-- 在rating分組的基礎上用rental_duration分組,再以rating字段升序排列
統計查詢
-- 統計查詢
-- 爲了對錶中數據有個初步瞭解,通常情況下我們要進行下簡單的統計查詢
-- 常用的統計函數有count、sum、avg、max、min等
select <統計函數>(字段名) from <數據庫>.<數據表>;
select * from sakila.payment; -- 以payment表爲例
select count(payment_id) from actor;
-- 有多少條顧客的購買記錄
select customer_id,sum(amount) from payment where customer_id = 1;
-- 編號爲1的顧客的付款總額
select customer_id,sum(amount) from payment group by customer_id;
-- 每個顧客的付款總額
select customer_id,avg(amount) from payment group by customer_id;
-- 每個顧客的平均付款額
select customer_id,max(amount),min(amount) from payment group by customer_id;
-- 每個顧客單次付款的最大值和最小值
連接查詢
有時候我們需要查詢的數據分散在不同的表中,此時我們就需要將這些存放在不同的表中的數據連接起來,也稱多表查詢。
示例數據表
由於Sakila數據庫中的表的數據過多,因此,爲了演示方便,我們創建兩張新的數據表用來演示學習:
(順便複習一下DDL的相關語句的用法,豈不美哉?)
create table city1(
city_id smallint(5) unsigned not null auto_increment,
city varchar(50) not null,
country_id smallint(5) unsigned not null,
primary key(city_id)
)
select city_id,city,country_id from city limit 3;
-- 從city表中抽出前三條記錄放入新建的city1表
create table country1(
country_id smallint(5) unsigned not null auto_increment,
country varchar(50) not null,
primary key(country_id)
)
select country_id,country from country limit 2;
-- 從country表中抽出前兩條記錄放入新建的country1表
)
創建完成後的表是這樣的:
- City1表
- country1表
那麼下面就開始學習下如何進行連接查詢吧
交叉連接
交叉連接(Corss Join)也稱笛卡爾積,是將所連接的表進行笛卡爾積的運算。
假設交叉連接的表有A,B兩表,A表有行記錄,B表有行記錄,此時將返回行記錄。
select * from city1,country1;
-- 等價於 select * from city1 join country1;
內連接
內連接(Inner Join)是通過定義連接的表內數據之間的關係進行查詢
select * from <連接的表> inner join <被連接的表> on <條件表達式>;
注:觀察到我們創建的兩張表其共同字段 country_id 並沒有相同值,因此我們必須修改一張表的數據以使其滿足連接需要
update city1 set country_id = '1' where (city_id='1');
更改後的 City1 表的數據是這樣的:
此時我們進行內連接可以得到:
select * from city1 inner join country1
on city1.country_id = country1.country_id;
外連接
外連接(Outer Join)是相對於內連接而言的,它不僅顯示符合條件的記錄,也顯示不符合條件的某張表的數據:
- 左連接(Left Join):不僅顯示符合條件的記錄,也顯示不符合條件的左表的數據
select * from city1 left join country1 on city1.country_id = country1.country_id;
- 右連接(Right Join):不僅顯示符合條件的記錄,也顯示不符合條件的右表的數據
select * from city1 right join country1 on city1.country_id = country1.country_id;
子查詢
有時候我們通過一次查詢並不能得到想要的結果,需要在一次查詢的基礎上再進行查詢,這就是所謂的子查詢。
我們以 sakila數據庫的customer表和payment表 爲例,其數據如下:
- customer表
- payment表
下面進入正題:
select * from customer where
customer_id in (select customer_id from payment where amount>10);
-- 支付額大於10的顧客信息(顧客支付表和顧客信息表的聯合查詢)
-- 試試下面這個康康有啥子區別?
/* select * from customer inner join payment on
customer.customer_id=payment.customer_id and payment.amount>10; */
select * from customer where
exists (select customer_id from payment
where payment.customer_id=customer.customer_id and amount>10);
-- 效果同上,不同的是EXISTS先執行括號外語句
-- 這個不如上面那句簡單清晰,建議使用上面那個
下面再介紹兩個常用的函數any()
和all()
select * from customer where
customer_id < any(select distinct customer_id from payment where amount > 10);
-- 小於任意一個編號即可,即<max()
select * from customer where
customer_id < all(select distinct customer_id from payment where amount > 10);
-- 小於所有的編號,即<min()
聯合查詢
有時候我們需要將查詢到結果合併起來,這時候就需要用到聯合查詢:Union
-- 聯合查詢
select count(customer_id) from sakila.rental; -- 返回16045條結果
select count(customer_id) from payment; -- 返回16050條結果
select customer_id from rental union select customer_id from payment;
-- 自動去重,返回599條結果
select customer_id from rental union all select customer_id from payment;
-- 不去重,返回32093條結果