11-10
高級查詢
1.關聯查詢
作用:可以跨越多表查詢
--查詢出員工的名字和他所在部門的的名字
//錯誤
select first_name,name from s_emp,s_dept;
//錯誤的原因:
產生笛卡爾積(在查詢兩張表的時候,一張表中的數據與另一張表中的數據一一匹配),產生了冗余數據。
//古老的寫法:
select first_name,name from s_emp,s_dept where s_emp.deop_id = s_dept.id;
//現在的寫法:
select e.first_name,d.name from s_emp e
join s_dept d on e.dept_id = d.id;
語法:
select 列,列,列
from 表1 join 表2
on 表1外鍵=表2主鍵
案例:
-- 找出Sales 部門的所有員工
select * from s_emp e
join s_dept d on e.dept_id=d.id
where d.name = ‘Sales‘;
-- 找出在 Asia 地區工作的員工
select * from s_emp e
join s_dept d on e.dept_id = d.id
join s_region r on d.region_id = r.id
where r.name = ‘Asia‘;
--找出客戶‘Hamada Sport‘ 的所有訂單號、費用、下訂日期
select o.id,o.total,o.date_ordered,c.name from s_ord o
join s_customer c on o.customer_id = c.id
where c.name =‘Hamada Sport‘;
--找出所有在‘Asia‘客戶的信息
select * from s_region r
join s_customer c on c.region_id = r.id
where r.name = ‘Asia‘;
練習:
--查詢出客戶名字叫unisports的訂單信息
select o.* from s_ord o
join s_customer c on o.customer_id = c.id
where lower(c.name) =lower(‘unisports‘);
--查詢出設在北美的的部門名稱
select s.name from s_dept s
join s_region r on s.region_id = r.id
where r.name = ‘North America‘;
--查詢出在北美工作的員工姓名、工資、入職日期和職位
select e.first_name, e.salary ,e.start_date,e.title from s_emp e
join s_dept d on e.dept_id = d.id
join s_region r on d.region_id =r.id
where r.name = ‘North America‘;
--查詢出所有客戶名,及其訂單號
select c.name,o.id from s_customer c
left join s_ord o on o.customer_id = c.id
order by c.name
;
2.外聯接
左外聯[left outer join]
以關聯的左邊為準,即使右邊沒有與之匹配的記錄,則左邊的記錄也要
出現在結果集中,右邊全部以NULL值顯示。
右外聯[right outer join]
以關聯的右邊為準,即使左邊沒有與之匹配的記錄,則右邊的記錄也要
出現在結果集中,左邊全部以NULL值顯示。
補充:全外聯,交叉外聯
--查詢出所有客戶名,及其訂單號
select c.name,o.id from s_customer c
left join s_ord o on o.customer_id = c.id
order by c.name
;
--查詢所有訂單號,訂單費用以及訂單所對應的客戶名
select c.name,o.id,o.total from s_customer c
right join s_ord o on o.customer_id = c.id;
--找出Womansport所購買的訂單信息(訂單編號,費用,支付方式)
select o.id,o.total,o.payment_type from s_ord o
right join s_customer c on o.customer_id = c.id
where c.name = ‘Womansport‘;
--找出Operations部門工作的員工名,工資,並且按照工資降序排列
select e.first_name,e.salary from s_emp e
left join s_dept d on e.dept_id =d.id
where d.name = ‘Operations‘
order by e.salary desc;
註意:如何驗證:
--第一步:select * from s_emp;select * from s_dept;查看員工人數和部門個數,以及是否存在員工沒有分配部門的 情況,和是否存在新部門沒有員工的情況
--第二步:如果存在員工沒有分配部門,那麽以員工表為主表
--第三部:如果存在新部門沒有員工的情況,以部門表為主表
自關聯:
-- 查詢出所有的員工名以及員工的上司名
select e.firstname,m.fitstname from s_emp e
left join s_emp m on e.manager_id = m.id;
----
註:關聯的條件不一定總是做等值比較的。
==========================
3分組查詢
定義:利用內置的分組函數來查詢
所謂分組,就是看待數據的“角度”不同。
也就是把某類值相同的看做一組。
語法:
select 列名,組函數(列名)...from 表名
where 條件
group by 列
having 字句
order by 列
分組函數:
SUM([distinct] 列|表達式|值) 求和
AVG([distinct] 列|表達式|值) 求平均值
MAX(列|表達式|值) 求最大值
MIN(列|表達式|值) 求最小值
COUNT([distinct] 列|*) 求個數(包含null)
如:
-- 找出員工的最高、最低、平均、以及工資總和
select max(salary),min(salary),avg(salary),sum(salary) from s_emp;
-- 找出各部門員工的最高、最低、平均、以及工資總和
select dept_id, max(salary),min(salary),avg(salary),sum(salary) from s_emp
group by dept_id
order by dept_id
;
-- 找出41,42,50部門員工的最高、最低、平均、以及工資總
select dept_id, max(salary),min(salary),avg(salary),sum(salary) from s_emp
group by dept_id
having dept_id in(41,42,50)
order by dept_id
;
select dept_id, max(salary),min(salary),avg(salary),sum(salary) from s_emp
where dept_id in(41,42,50)
group by dept_id
order by dept_id
;
註意1:只有出現在group by 後面的列[用來做為分組條件的列],才有資格
寫在SELECT的後面,除非使用組函數進行修飾。
註意2:having 和where 都是條件
區別:
WHERE 子句中是不能使用 組函數的,因為它在GROUP BY 之前。
但是,HAVING 子句中可以使用組函數,因為它在GROUP BY 之後。
-- 統計各個職稱中工資高於1100的各有多少人。
select count(*),title
from s_emp
where salary >1100
group by title;
-- 找出訂單數量超過>=2個的客戶
select c.name
from s_customer c join s_ord o on o.customer_id = c.id
group by c.id,c.name
having count(o.id)>=2;
-- 統計共計多少個員工
select count(e.id) from s_emp e;
-- 統計共計多少個職稱[不能重復]
select count(distinct title) from s_emp;
練習:
--1.找出超過(含)4個員工的部門id及部門名稱
select d.id,d.name,count(*) from s_emp e
left join s_dept d on e.dept_id = d.id
group by d.id,d.name
having count(*)>=4;
--2.找出訂單總費用超過10000元的客戶
select c.name,c.id from s_customer c
left join s_ord o on c.id = o.customer_id
where o.total>=10000
group by c.name,c.id;
--3.統計各區域的客戶數量,按它的降序排序
select r.id,r.name,count(*) from s_region r
join s_customer c on c.region_id = r.id
group by r.id ,r.name
order by count(*)desc;
--4.統計各經理的所管理的員工數
select e.manager_id ,count(e.id) from s_emp e
left join s_emp m on e.manager_id = m.id
group by e.manager_id;
--5.統計訂單中各種支付的費用
select sum(o.total) 費用,o.payment_type 支付方式 from s_ord o group by o.payment_type;
11-10