MySQL練習(1)——牛客網[xiaoshun]

1、牛客網網址mysql

https://www.nowcoder.com/ta/sql,一共76道真題。sql

PS:不要過於相信在線編譯器!!!作完每一題要記得看各位網友大神解讀和總結。express

2、題目函數

一、查找最晚入職員工的全部信息,爲了減輕入門難度,目前全部的數據裏員工入職的日期都不是同一天(sqlite裏面的註釋爲--,mysql爲comment)
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`));性能

解題:spa

(1)假設員工入職的日期都不是同一天,日期降序排序後,直接截取第一條數據便可。code

select * from employees order by hire_date desc limit 1;

  limit m,n:m爲起始索引位置(索引從0開始),日後獲取n行數據。如limit 6,10 獲取第7行到16行數據。另外一種寫法:limit n offset msqlite

  limit 語句運行順序排到最後,由於它是從結果集中截取部分行數。blog

(2)假設員工入職的日期有可能同一天。排序

select *
from employees
where hire_date = (
    select max(hire_date)
    from employees);
#1.用子查詢獲取最遲入職日期;
#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`));

解題:

(1)假設員工入職的日期都不是同一天

select * from employees order by hire_date desc limit 2,1;
# 直接降序排序獲取第三行記錄便可

(2)假設員工入職的日期有可能同一天

select *
from employees
where hire_date=(
    select distinct hire_date
    from employees
    order by hire_date desc
    limit 1 offset 2
);
#1.先用distinct把重複的日期去重,獲得的日期都是惟一的
#2.再排序後,用limit獲取倒數第三天入職的日期
#3.最後把入職日期等於倒數第三天日期的員工信息所有獲取

三、

查找各個部門當前(dept_manager.to_date='9999-01-01')領導當前(salaries.to_date='9999-01-01')薪水詳情以及其對應部門編號dept_no
(注:請以salaries表爲主表進行查詢,輸出結果以salaries.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`));

CREATE TABLE `dept_manager` (
`dept_no` char(4) NOT NULL, -- '部門編號'
`emp_no` int(11) NOT NULL, --  '員工編號'
`to_date` date NOT NULL,
PRIMARY KEY (`emp_no`,`dept_no`));

解題:

select sa.*, dm.dept_no
from  salaries as sa
inner join dept_manager as dm
on dm.emp_no = sa.emp_no
where sa.to_date='9999-01-01'
and dm.to_date='9999-01-01'
order by sa.emp_no asc;
# 考察表的內鏈接和一些實際狀況業務的瞭解

四、查找全部已經分配部門的員工的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`));

解題:

select last_name, first_name, dept_no
from employees e
inner join dept_emp d
on e.emp_no = d.emp_no
where dept_no is not null;
# 考察表內鏈接,不用指定dept_no是否爲null,由於內鏈接中,任何一邊有缺失數據就不會顯示。

五、查找全部員工的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`));

select last_name,first_name,dept_no
from employees e
left join dept_emp d
on e.emp_no = d.emp_no;
#即便沒有分配部門的員工也要顯示,意味着employees表中全部emp_no都要顯示,無論dept_emp表的對應dept_no是否缺失。考察左鏈接

多表鏈接查詢知識點總結:

表1 inner join 表2  兩邊表同時有對應的數據,即任何一邊有缺失數據就不顯示;

主 left join 從    左邊主表的數據所有讀取,右邊從邊無對應數據的填充NULL值;

從 right join 主    反之;

 

六、查找全部員工入職時候的薪水狀況,給出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`));

解題:

(1)錶鏈接

select e.emp_no, s.salary
from employees e
inner join salaries s
on e.emp_no = s.emp_no
where s.from_date = e.hire_date
order by e.emp_no desc;
# 1.有漲薪或者降薪,說明salaries表中的每個emp_no至少有一個,薪水變過就有重複值。
# 2.只要from_date等於入職日期hire_date,薪水就是入職時的薪水。

(2)分組以後求日期最小值

select emp_no,salary
from salaries
group by emp_no
having min(from_date)
order by emp_no desc;
# 1.先用emp_no分組,獲得每一個員工分組數據
# 2.再用having對每一個分組求最先日期,即剛入職的日期,不能求最小工資,由於員工有可能被降薪。
# 3.數據量大時,不建議用分組查詢,由於having以後,程序會在每一個分組表中在遍歷一遍,可能致使性能不佳。

七、查找薪水變更超過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`));

解題:

select emp_no,count(*) as t
from salaries
group by emp_no
having count(*) > 15;
# 考察點是分組統計查詢,

分組聚合篩選查詢知識點概括:

語法:
SELECT column1, column2, ... column_n, aggregate_function (expression),constant
FROM tables
WHERE predicates
GROUP BY column1, column2, ... column_n
HAVING condition1 ... condition_n;

重點:

  • 分組後SELECT後能夠出現:聚合字段(即group by後出現的字段)、集合函數輸入值aggregate_function (expression)、常量。必須嚴格準守吖!否則錯了也不知道;

  (12題,有典型的錯誤例子。)

  • having語句彌補了where關鍵字不能與與聚合函數聯合使用的不足,可是要注意的是,having語句篩選的是分組,而不是分組中的某行記錄;
  • where篩選的是原表,having是對各個分組表進行篩選判斷,因此儘可能在where中把原表篩選到最小,分組後每一個表篩選遍歷的速度就會加快了。

八、找出全部員工當前(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`));

解題:

(1)distinct關鍵字排除重複

select distinct salary
from salaries
where to_date='9999-01-01'
order by salary desc;
# distinct 多列去重時,只有全部列的信息徹底一致才認爲時重複的。

(2)用group by去重,聽說數據量很大時,效率比較高

select salary
from salaries
where to_date='9999-01-01'
group by salary
order by salary desc;

九、獲取全部部門當前(dept_manager.to_date='9999-01-01')manager的當前(salaries.to_date='9999-01-01')薪水狀況,給出dept_no, emp_no以及salary(請注意,同一我的可能有多條薪水狀況記錄)
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`));

解題:

select dept_no,d.emp_no,salary
from dept_manager d
inner join salaries s
on d.emp_no = s.emp_no
where d.to_date='9999-01-01'
and s.to_date='9999-01-01';

十、獲取全部非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`));
解題:
(1)左外鏈接
select e.emp_no
from employees e
left join dept_manager d
on e.emp_no = d.emp_no
where d.dept_no is null;
# 1.假如員工不是manager,那麼dept_no字段應該爲null
# 2.經過左鏈接的方式,使不是manager的dept_no字段爲null,再篩選便可

(2)子查詢

select emp_no
from employees
where emp_no not in(
    select d.emp_no
    from dept_manager d
    inner join employees e
    on d.emp_no = e.emp_no
);
# 1.先用子查詢查出是manger的emp_no
# 2.再判斷員工emp_no不在manger的emp_no裏面便可
# 3.子查詢能夠直接用select emp_no from dept_manager,畢竟dept_manager這個表存的是manage的信息。

十一、獲取全部員工當前的(dept_manager.to_date='9999-01-01')manager,若是員工是manager的話不顯示(也就是若是當前的manager是本身的話結果不顯示)。輸出結果第一列給出當前員工的emp_no,第二列給出其manager對應的emp_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`));
解題:
select de.emp_no, dm.emp_no as manager_no
from dept_emp de
inner join dept_manager dm
on dm.dept_no = de.dept_no
where de.emp_no <> dm.emp_no
and dm.to_date='9999-01-01'
and de.to_date='9999-01-01';
# 1.兩表內鏈接後,只有manager的de.emp_no和dm.emp_no是同樣的,用where篩選掉便可。
# 2.由於部門的manager有可能會離職或者更換,要保證manage和普通員工都在同一時間在同一部門才能構成從屬關係。兩個跨時空的人戀愛會很慘的!!!

 十二、獲取全部部門中當前(dept_emp.to_date = '9999-01-01')員工當前(salaries.to_date='9999-01-01')薪水最高的相關信息,給出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`));
相關文章
相關標籤/搜索