資料庫SQL實戰:MySql練習(上)
文章目錄
- 1. 查詢最晚入職員工的所有資訊
- 2. 查詢入職員工時間排名倒數第三的員工所有資訊
- 3. 查詢各個部門當前(to_date='9999-01-01')領導當前薪水詳情以及其對應部門編號dept_no
- 4. 查詢所有已經分配部門的員工的last_name和first_name
- 5. 查詢所有員工的last_name和first_name以及對應部門編號dept_no,也包括展示沒有分配具體部門的員工
- 6. 查詢所有員工入職時候的薪水情況,給出emp_no以及salary, 並按照emp_no進行逆序
- 7. 查詢薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t
- 8. 找出所有員工當前(to_date='9999-01-01')具體的薪水salary情況,對於相同的薪水只顯示一次,並按照逆序顯示
- 9. 獲取所有部門當前manager的當前薪水情況,給出dept_no, emp_no以及salary,當前表示to_date='9999-01-01'
- 10. 獲取所有非manager的員工emp_no
- 11. 獲取所有員工當前的manager,如果當前的manager是自己的話結果不顯示,當前表示to_date='9999-01-01'。結果第一列給出當前員工的emp_no,第二列給出其manager對應的manager_no。
- 12. 獲取所有部門中當前員工薪水最高的相關資訊,給出dept_no, emp_no以及其對應的salary
- 13. 從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t
- 14. 從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。
- 15. 查詢employees表所有emp_no為奇數,且last_name不為Mary的員工資訊,並按照hire_date逆序排列
- 16. 統計出當前各個title型別對應的員工當前薪水對應的平均工資。結果給出title以及平均工資avg
- 17. 獲取當前(to_date='9999-01-01')薪水第二多的員工的emp_no以及其對應的薪水salary
- 18. 查詢當前薪水(to_date='9999-01-01')排名第二多的員工編號emp_no、薪水salary、last_name以及first_name,不準使用order by
- 19. 查詢所有員工的last_name和first_name以及對應的dept_name,也包括暫時沒有分配部門的員工
- 20. 查詢員工編號emp_no為10001其自入職以來的薪水salary漲幅值growth
- 21. 查詢所有員工自入職以來的薪水漲幅情況,給出員工編號emp_no以及其對應的薪水漲幅growth,並按照growth進行升序
- 22. 統計各個部門對應員工漲幅的次數總和,給出部門編碼dept_no、部門名稱dept_name以及次數sum
- 23. 對所有員工的當前(to_date='9999-01-01')薪水按照salary進行按照1-N的排名,相同salary並列且按照emp_no升序排列
- 24. 獲取所有非manager員工當前的薪水情況,給出dept_no、emp_no以及salary ,當前表示to_date='9999-01-01'
- 25. 獲取員工其當前的薪水比其manager當前薪水還高的相關資訊,當前表示to_date='9999-01-01',結果第一列給出員工的emp_no,第二列給出其manager的manager_no,第三列給出該員工當前的薪水emp_salary,第四列給該員工對應的manager當前的薪水manager_salary
- 26. 彙總各個部門當前員工的title型別的分配數目,結果給出部門編號dept_no、dept_name、其當前員工所有的title以及該型別title對應的數目count
- 27. 給出每個員工每年薪水漲幅超過5000的員工編號emp_no、薪水變更開始日期from_date以及薪水漲幅值salary_growth,並按照salary_growth逆序排列。 提示:在sqlite中獲取datetime時間對應的年份函式為strftime('%Y', to_date)
- 28. 查詢描述資訊中包括robot的電影對應的分類名稱以及電影數目,而且還需要該分類對應電影數量>=5部
- 29. 使用join查詢方式找出沒有分類的電影id以及名稱
- 30. 使用子查詢的方式找出屬於Action分類的所有電影對應的title,description
1. 查詢最晚入職員工的所有資訊
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
- sql語句
select *
from employees
where hire_date = (select max(hire_date) from employees);
2. 查詢入職員工時間排名倒數第三的員工所有資訊
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
- sql語句
select *
from employees
order by hire_date
desc limit 2,1;
3. 查詢各個部門當前(to_date=‘9999-01-01’)領導當前薪水詳情以及其對應部門編號dept_no
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
- sql語句
select s.*, d.dept_no
from salaries s
join dept_manager d
on d.emp_no = s.emp_no
andd.to_date='9999-01-01'
and s.to_date='9999-01-01';
JOIN 按照功能大致分為如下三類:
INNER JOIN/JOIN(內連線,或等值連線):取得兩個表中存在連線匹配關係的記錄。
LEFT JOIN(左連線):取得左表(table1)完全記錄,即是右表(table2)並無對應匹配記錄。
RIGHT JOIN(右連線):與 LEFT JOIN 相反,取得右表(table2)完全記錄,即是左表(table1)並無匹配對應記錄。注意:mysql不支援Full join,不過可以通過UNION 關鍵字來合併 LEFT JOIN 與 RIGHT JOIN來模擬FULL join.
4. 查詢所有已經分配部門的員工的last_name和first_name
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
- sql語句
select e.last_name, e.first_name,d.dept_no
from dept_emp d
left join employees e
on e.emp_no = d.emp_no;
5. 查詢所有員工的last_name和first_name以及對應部門編號dept_no,也包括展示沒有分配具體部門的員工
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
- sql語句
select e.last_name, e.first_name, d.dept_no
from employees e
left join dept_emp d
on e.emp_no = d.emp_no;
6. 查詢所有員工入職時候的薪水情況,給出emp_no以及salary, 並按照emp_no進行逆序
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
- sql語句
select e.emp_no,s.salary
from employees e
join salaries s
on e.emp_no = s.emp_no
and e.hire_date = s.from_date
order by e.emp_no desc;
此題應注意以下四個知識點:
1、由於測試資料中,salaries.emp_no 不唯一(因為號碼為 emp_no 的員工會有多次漲薪的可能,所以在 salaries 中對應的記錄不止一條),employees.emp_no 唯一,即 salaries 的資料會多於 employees,因此需先找到 employees.emp_no 在 salaries 表中對應的記錄salaries.emp_no,則有限制條件 e.emp_no = s.emp_no;
2、根據題意注意到 salaries.from_date 和 employees.hire_date 的值應該要相等,因此有限制條件 e.hire_date = s.from_date;
3、根據題意要按照 emp_no 值逆序排列,因此最後要加上 ORDER BY e.emp_no DESC;
4、為了程式碼良好的可讀性,運用了 Alias 別名語句,將 employees 簡化為 e,salaries 簡化為s,即 employees AS e 與 salaries AS s,其中 AS 可以省略。
7. 查詢薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
- sql語句
select emp_no,count(emp_no) count
from salaries
group by emp_no
having count >15;
where、having之間的區別和用法:
where 後不能跟聚合函式,因為where執行順序大於聚合函式。
where 子句的作用是在對查詢結果進行分組前,將不符合where條件的行去掉,即在分組之前過濾資料,條件中不能包含聚組函式,使用where條件顯示特定的行。
having 子句的作用是篩選滿足條件的組,即在分組之後過濾資料,條件中經常包含聚組函式,使用having 條件顯示特定的組,也可以使用多個分組標準進行分組。
8. 找出所有員工當前(to_date=‘9999-01-01’)具體的薪水salary情況,對於相同的薪水只顯示一次,並按照逆序顯示
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
- sql語句
select salary
from salaries
where to_date='9999-01-01'
group by salary
order by salary desc;
select distinct(salary)
from salaries
where to_date='9999-01-01'
order by salary desc;
在不同記錄數較小時,count group by效能普遍高於count distinct,尤其對於text型別表現的更明顯。而對於不同記錄數較大的場景,count group by效能反而低於直接count distinct。
9. 獲取所有部門當前manager的當前薪水情況,給出dept_no, emp_no以及salary,當前表示to_date=‘9999-01-01’
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
- sql語句
select d.dept_no, d.emp_no, s.salary
from salaries s
join dept_manager d
on d.emp_no = s.emp_no
and d.to_date = '9999-01-01'
and s.to_date = '9999-01-01';
10. 獲取所有非manager的員工emp_no
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
- sql語句
select emp_no
from employees
where emp_no not in (select emp_no from dept_manager)
select e.emp_no
from employees e
left join dept_manager d
on e.emp_no = d.emp_no
where d.emp_no is null;
方法一:使用NOT IN選出在employees但不在dept_manager中的emp_no記錄。
方法二:先使用LEFT JOIN連線兩張表,再從此表中選出dept_no值為NULL對應的emp_no記錄。
因為not in會轉化成多表連線,而且不使用索引。所以用left_join會好一點。
11. 獲取所有員工當前的manager,如果當前的manager是自己的話結果不顯示,當前表示to_date=‘9999-01-01’。結果第一列給出當前員工的emp_no,第二列給出其manager對應的manager_no。
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL,
`emp_no` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
- sql語句
select de.emp_no, dm.emp_no manager_no
from dept_emp de inner join dept_manager dm
on de.dept_no = dm.dept_no
where dm.to_date = '9999-01-01' and de.to_date = '9999-01-01' and de.emp_no <> dm.emp_no;
12. 獲取所有部門中當前員工薪水最高的相關資訊,給出dept_no, emp_no以及其對應的salary
CREATE TABLE `dept_emp` (
`emp_no` int(11) NOT NULL,
`dept_no` char(4) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
- sql語句
select d.dept_no,s.emp_no,max(salary) salary
from salaries s
join dept_emp d
on s.emp_no = d.emp_no
and d.to_date = '9999-01-01'
and s.to_date = '9999-01-01'
group by d.dept_no;
13. 從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t
CREATE TABLE IF NOT EXISTS "titles" (
`emp_no` int(11) NOT NULL,
`title` varchar(50) NOT NULL,
`from_date` date NOT NULL,
`to_date` date DEFAULT NULL);
- sql語句
select title,count(title) t
from titles
group by title
having t>=2;
14. 從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。
注意對於重複的emp_no進行忽略。
CREATE TABLE IF NOT EXISTS "titles" (
`emp_no` int(11) NOT NULL,
`title` varchar(50) NOT NULL,
`from_date` date NOT NULL,
`to_date` date DEFAULT NULL);
- sql語句
select title, count(distinct emp_no) t
from titles
group by title
having t>=2;
15. 查詢employees表所有emp_no為奇數,且last_name不為Mary的員工資訊,並按照hire_date逆序排列
CREATE TABLE `employees` (
`emp_no` int(11) NOT NULL,
`birth_date` date NOT NULL,
`first_name` varchar(14) NOT NULL,
`last_name` varchar(16) NOT NULL,
`gender` char(1) NOT NULL,
`hire_date` date NOT NULL,
PRIMARY KEY (`emp_no`));
- sql語句
select *
from employees
where emp_no%2=1
and last_name <> 'Mary'
order by hire_date
desc;
16. 統計出當前各個title型別對應的員工當前薪水對應的平均工資。結果給出title以及平均工資avg
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary` int(11) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`from_date`));
CREATE TABLE IF NOT EXISTS "titles" (
`emp_no` int(11) NOT NULL,
`title` varchar(50) NOT NULL,
`from_date` date NOT NULL,
`to_date` date DEFAULT NULL);
- sql語句
select t.title,avg(s.salary) avg
from titles t
join salaries s
on s.emp_no = t.emp_no
and s.to_date = '9999-01-01'
and t.to_date = '9999-01-01'
group by t.title;
17. 獲取當前(to_date=‘9999-01-01’)薪水第二多的員工的emp_no以及其對應的薪水salary
CREATE TABLE `salaries` (
`emp_no` int(11) NOT NULL,
`salary`