


解答:
本題應(yīng)該考慮降薪的問(wèn)題:
題中沒(méi)有講員工不降薪,所以不能直接使用最大薪水-最小薪水求值,例如:我入職薪水100元,過(guò)程中降薪20元,現(xiàn)在工資80元,那么按照(最大薪水-最小薪水求值),薪水還漲了20元,但實(shí)際是降薪20元,所有有錯(cuò)誤。
實(shí)際應(yīng)該使用最后記錄薪水-入職時(shí)薪水(80-100),漲幅為-20元。
select b.emp_no,(b.salary-a.salary) as growth
from
(select e.emp_no,s.salary
from employees e left join salaries? s on e.emp_no=s.emp_no
and e.hire_date=s.from_date)a -- 入職工資表
inner join
(select e.emp_no,s.salary
from employees e left join salaries? s on e.emp_no=s.emp_no
where s.to_date='9999-01-01')b -- 現(xiàn)在工資表
on a.emp_no=b.emp_no
order by growth
這道題寫(xiě)了很久,其實(shí)主要就是做兩個(gè)表,然后剛?cè)肼毜男劫Y減去現(xiàn)在的薪資,按照增長(zhǎng)高低排序即可
SQL22?統(tǒng)計(jì)各個(gè)部門(mén)的工資記錄數(shù)




解答(來(lái)源于討論區(qū))
方法1:嵌套查詢,查出一個(gè)dept_no,就進(jìn)行子查詢的到對(duì)應(yīng)COUNT()
SELECT d.dept_no,d.dept_name,count(s.salary) as sum
FROM salaries as s
LEFT join dept_emp as de on de.emp_no = s.emp_no
LEFT join departments as d on d.dept_no = de.dept_no
GROUP BY d.dept_no ORDER BY d.dept_no asc
注意:對(duì)于這種情形的子查詢,一個(gè)部門(mén)進(jìn)去,必須只返回一個(gè)值,而且只能查詢一個(gè)列,可以參考26題的錯(cuò)誤示范做對(duì)比
方法2:先進(jìn)行兩次內(nèi)連接,再通過(guò)GROUP BY查詢
SELECT de.dept_no, de.dept_name, COUNT(*) AS sum
FROM (SELECT *
FROM departments
INNER JOIN dept_emp
ON departments.dept_no=dept_emp.dept_no) AS de
INNER JOIN salaries AS s
ON de.emp_no=s.emp_no
GROUP BY de.dept_no;
注意:這里GROUP BY聚合dept_no,而dept_name看上去不是聚合列(因此似乎不能放進(jìn)SELECT語(yǔ)句內(nèi)),但是事實(shí)上,由于dept_no是主鍵,所以一個(gè)dept_no只會(huì)對(duì)應(yīng)一個(gè)dept_name,所以可以認(rèn)為dept_name是可聚合的,所以可以放進(jìn)去。特別要注意的是,如果dept_no不是主鍵,而是聯(lián)合主鍵之一或者別的情況,總之dept_no不能唯一確定dept_name,那么即使在表中看上去dept_no和dept_name是一一對(duì)應(yīng)的,也不能將dept_name放進(jìn)SELECT中,強(qiáng)行放進(jìn)去,在mysql中也會(huì)報(bào)錯(cuò)(當(dāng)然在題庫(kù)中不會(huì)報(bào)錯(cuò))。
補(bǔ)充:內(nèi)層的內(nèi)連接,可以省略SELECT?(因?yàn)閮?nèi)連接自己會(huì)生成臨時(shí)表):
SELECT de.dept_no, de.dept_name, COUNT(
) AS sum
FROM (departments
INNER JOIN dept_emp
ON departments.dept_no=dept_emp.dept_no) AS de
INNER JOIN salaries AS s
ON de.emp_no=s.emp_no
GROUP BY de.dept_no;
補(bǔ)充:還可以進(jìn)一步省略,直接進(jìn)行連續(xù)內(nèi)連接:
SELECT d.dept_no, d.dept_name, COUNT(*) AS sum
FROM
(departments AS d
INNER JOIN dept_emp AS de
ON d.dept_no=de.dept_no
INNER JOIN salaries AS s
ON de.emp_no=s.emp_no)
GROUP BY de.dept_no;
注意:連續(xù)內(nèi)連接中一定不要出現(xiàn)WHERE(21題的經(jīng)驗(yàn))
方法3:直接三表聯(lián)查,用WHERE過(guò)濾
SELECT d.dept_no, d.dept_name, COUNT(*) AS sum
FROM departments AS d, dept_emp AS de, salaries AS s
WHERE d.dept_no=de.dept_no
AND de.emp_no=s.emp_no
GROUP BY d.dept_no;
備注:三表聯(lián)查在代碼上比進(jìn)行兩次內(nèi)連接簡(jiǎn)潔
我的解答:將三個(gè)表連接再一起,然后利用count()函數(shù)來(lái)計(jì)數(shù),最后利用group by來(lái)分組,以及order by 來(lái)排序
SELECT d.dept_no,d.dept_name,count(s.salary) as sum
FROM salaries as s
LEFT join dept_emp as de
on de.emp_no = s.emp_no
LEFT join departments as d
on d.dept_no = de.dept_no
GROUP BY d.dept_no
ORDER BY d.dept_no asc
SQL23?對(duì)所有員工的薪水按照salary降序進(jìn)行1-N的排名


解答(來(lái)源于討論區(qū)):
這道題目考察的是SQL窗口函數(shù)(OLAP函數(shù))中用于排序的專(zhuān)用窗口函數(shù)用法
但是由于關(guān)系數(shù)據(jù)庫(kù)提供支持OLAP用途功能時(shí)間不長(zhǎng)
還有一部分DBMS不支持這個(gè)新功能(比如MYSQL)
select?emp_no,?salary,
???????dense_rank()?over?(order?by?salary?desc)?as?rank
from?salaries
where?to_date='9999-01-01'
order?by?rank?asc,emp_no?asc;
下面介紹三種用于進(jìn)行排序的專(zhuān)用窗口函數(shù):
1、RANK()
在計(jì)算排序時(shí),若存在相同位次,會(huì)跳過(guò)之后的位次。
例如,有3條排在第1位時(shí),排序?yàn)椋?,1,1,4······
2、DENSE_RANK()
這就是題目中所用到的函數(shù),在計(jì)算排序時(shí),若存在相同位次,不會(huì)跳過(guò)之后的位次。
例如,有3條排在第1位時(shí),排序?yàn)椋?,1,1,2······
3、ROW_NUMBER()
這個(gè)函數(shù)賦予唯一的連續(xù)位次。
例如,有3條排在第1位時(shí),排序?yàn)椋?,2,3,4······
窗口函數(shù)用法:
<窗口函數(shù)> OVER ( [PARTITION BY <列清單> ]
????????????????????????????? ? ORDER BY <排序用列清單> )
*其中[ ]中的內(nèi)容可以忽略
我的解答:
SELECT emp_no,salary,dense_rank() over(ORDER BY salary DESC) as t_rank
FROM salaries
GROUP BY emp_no