數據庫-SQL語句練習【已完成26題,還剩35題】

練習題連接:https://www.nowcoder.com/ta/sql?page=0html

錯題頻次表
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    1+1 1+1   1-1 1-1         1    1    
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
   1  1   4     1 0.5   1              
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
                               
49 50 51 52 53 54 55 56 57 58 59 60 61      
                               

 

練習數據庫內容:java

建立salaries表格sql

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`));
View Code

插入salaries內容數據庫

INSERT INTO salaries VALUES(10001,60117,'1986-06-26','1987-06-26'); INSERT INTO salaries VALUES(10001,62102,'1987-06-26','1988-06-25'); INSERT INTO salaries VALUES(10001,66074,'1988-06-25','1989-06-25'); INSERT INTO salaries VALUES(10001,66596,'1989-06-25','1990-06-25'); INSERT INTO salaries VALUES(10001,66961,'1990-06-25','1991-06-25'); INSERT INTO salaries VALUES(10001,71046,'1991-06-25','1992-06-24'); INSERT INTO salaries VALUES(10001,74333,'1992-06-24','1993-06-24'); INSERT INTO salaries VALUES(10001,75286,'1993-06-24','1994-06-24'); INSERT INTO salaries VALUES(10001,75994,'1994-06-24','1995-06-24'); INSERT INTO salaries VALUES(10001,76884,'1995-06-24','1996-06-23'); INSERT INTO salaries VALUES(10001,80013,'1996-06-23','1997-06-23'); INSERT INTO salaries VALUES(10001,81025,'1997-06-23','1998-06-23'); INSERT INTO salaries VALUES(10001,81097,'1998-06-23','1999-06-23'); INSERT INTO salaries VALUES(10001,84917,'1999-06-23','2000-06-22'); INSERT INTO salaries VALUES(10001,85112,'2000-06-22','2001-06-22'); INSERT INTO salaries VALUES(10001,85097,'2001-06-22','2002-06-22'); INSERT INTO salaries VALUES(10001,88958,'2002-06-22','9999-01-01'); INSERT INTO salaries VALUES(10002,72527,'1996-08-03','1997-08-03'); INSERT INTO salaries VALUES(10002,72527,'1997-08-03','1998-08-03'); INSERT INTO salaries VALUES(10002,72527,'1998-08-03','1999-08-03'); INSERT INTO salaries VALUES(10002,72527,'1999-08-03','2000-08-02'); INSERT INTO salaries VALUES(10002,72527,'2000-08-02','2001-08-02'); INSERT INTO salaries VALUES(10002,72527,'2001-08-02','9999-01-01'); INSERT INTO salaries VALUES(10003,40006,'1995-12-03','1996-12-02'); INSERT INTO salaries VALUES(10003,43616,'1996-12-02','1997-12-02'); INSERT INTO salaries VALUES(10003,43466,'1997-12-02','1998-12-02'); INSERT INTO salaries VALUES(10003,43636,'1998-12-02','1999-12-02'); INSERT INTO salaries VALUES(10003,43478,'1999-12-02','2000-12-01'); INSERT INTO salaries VALUES(10003,43699,'2000-12-01','2001-12-01'); INSERT INTO salaries VALUES(10003,43311,'2001-12-01','9999-01-01'); INSERT INTO salaries VALUES(10004,40054,'1986-12-01','1987-12-01'); INSERT INTO salaries VALUES(10004,42283,'1987-12-01','1988-11-30'); INSERT INTO salaries VALUES(10004,42542,'1988-11-30','1989-11-30'); INSERT INTO salaries VALUES(10004,46065,'1989-11-30','1990-11-30'); INSERT INTO salaries VALUES(10004,48271,'1990-11-30','1991-11-30'); INSERT INTO salaries VALUES(10004,50594,'1991-11-30','1992-11-29'); INSERT INTO salaries VALUES(10004,52119,'1992-11-29','1993-11-29'); INSERT INTO salaries VALUES(10004,54693,'1993-11-29','1994-11-29'); INSERT INTO salaries VALUES(10004,58326,'1994-11-29','1995-11-29'); INSERT INTO salaries VALUES(10004,60770,'1995-11-29','1996-11-28'); INSERT INTO salaries VALUES(10004,62566,'1996-11-28','1997-11-28'); INSERT INTO salaries VALUES(10004,64340,'1997-11-28','1998-11-28'); INSERT INTO salaries VALUES(10004,67096,'1998-11-28','1999-11-28'); INSERT INTO salaries VALUES(10004,69722,'1999-11-28','2000-11-27'); INSERT INTO salaries VALUES(10004,70698,'2000-11-27','2001-11-27'); INSERT INTO salaries VALUES(10004,74057,'2001-11-27','9999-01-01'); INSERT INTO salaries VALUES(10005,78228,'1989-09-12','1990-09-12'); INSERT INTO salaries VALUES(10005,82621,'1990-09-12','1991-09-12'); INSERT INTO salaries VALUES(10005,83735,'1991-09-12','1992-09-11'); INSERT INTO salaries VALUES(10005,85572,'1992-09-11','1993-09-11'); INSERT INTO salaries VALUES(10005,85076,'1993-09-11','1994-09-11'); INSERT INTO salaries VALUES(10005,86050,'1994-09-11','1995-09-11'); INSERT INTO salaries VALUES(10005,88448,'1995-09-11','1996-09-10'); INSERT INTO salaries VALUES(10005,88063,'1996-09-10','1997-09-10'); INSERT INTO salaries VALUES(10005,89724,'1997-09-10','1998-09-10'); INSERT INTO salaries VALUES(10005,90392,'1998-09-10','1999-09-10'); INSERT INTO salaries VALUES(10005,90531,'1999-09-10','2000-09-09'); INSERT INTO salaries VALUES(10005,91453,'2000-09-09','2001-09-09'); INSERT INTO salaries VALUES(10005,94692,'2001-09-09','9999-01-01'); INSERT INTO salaries VALUES(10006,43311,'1990-08-05','1991-08-05'); INSERT INTO salaries VALUES(10006,43311,'1991-08-05','1992-08-04'); INSERT INTO salaries VALUES(10006,43311,'1992-08-04','1993-08-04'); INSERT INTO salaries VALUES(10006,43311,'1993-08-04','1994-08-04'); INSERT INTO salaries VALUES(10006,43311,'1994-08-04','1995-08-04'); INSERT INTO salaries VALUES(10006,43311,'1995-08-04','1996-08-03'); INSERT INTO salaries VALUES(10006,43311,'1996-08-03','1997-08-03'); INSERT INTO salaries VALUES(10006,43311,'1997-08-03','1998-08-03'); INSERT INTO salaries VALUES(10006,43311,'1998-08-03','1999-08-03'); INSERT INTO salaries VALUES(10006,43311,'1999-08-03','2000-08-02'); INSERT INTO salaries VALUES(10006,43311,'2000-08-02','2001-08-02'); INSERT INTO salaries VALUES(10006,43311,'2001-08-02','9999-01-01'); INSERT INTO salaries VALUES(10007,56724,'1989-02-10','1990-02-10'); INSERT INTO salaries VALUES(10007,60740,'1990-02-10','1991-02-10'); INSERT INTO salaries VALUES(10007,62745,'1991-02-10','1992-02-10'); INSERT INTO salaries VALUES(10007,63475,'1992-02-10','1993-02-09'); INSERT INTO salaries VALUES(10007,63208,'1993-02-09','1994-02-09'); INSERT INTO salaries VALUES(10007,64563,'1994-02-09','1995-02-09'); INSERT INTO salaries VALUES(10007,68833,'1995-02-09','1996-02-09'); INSERT INTO salaries VALUES(10007,70220,'1996-02-09','1997-02-08'); INSERT INTO salaries VALUES(10007,73362,'1997-02-08','1998-02-08'); INSERT INTO salaries VALUES(10007,75582,'1998-02-08','1999-02-08'); INSERT INTO salaries VALUES(10007,79513,'1999-02-08','2000-02-08'); INSERT INTO salaries VALUES(10007,80083,'2000-02-08','2001-02-07'); INSERT INTO salaries VALUES(10007,84456,'2001-02-07','2002-02-07'); INSERT INTO salaries VALUES(10007,88070,'2002-02-07','9999-01-01'); INSERT INTO salaries VALUES(10008,46671,'1998-03-11','1999-03-11'); INSERT INTO salaries VALUES(10008,48584,'1999-03-11','2000-03-10'); INSERT INTO salaries VALUES(10008,52668,'2000-03-10','2000-07-31'); INSERT INTO salaries VALUES(10009,60929,'1985-02-18','1986-02-18'); INSERT INTO salaries VALUES(10009,64604,'1986-02-18','1987-02-18'); INSERT INTO salaries VALUES(10009,64780,'1987-02-18','1988-02-18'); INSERT INTO salaries VALUES(10009,66302,'1988-02-18','1989-02-17'); INSERT INTO salaries VALUES(10009,69042,'1989-02-17','1990-02-17'); INSERT INTO salaries VALUES(10009,70889,'1990-02-17','1991-02-17'); INSERT INTO salaries VALUES(10009,71434,'1991-02-17','1992-02-17'); INSERT INTO salaries VALUES(10009,74612,'1992-02-17','1993-02-16'); INSERT INTO salaries VALUES(10009,76518,'1993-02-16','1994-02-16'); INSERT INTO salaries VALUES(10009,78335,'1994-02-16','1995-02-16'); INSERT INTO salaries VALUES(10009,80944,'1995-02-16','1996-02-16'); INSERT INTO salaries VALUES(10009,82507,'1996-02-16','1997-02-15'); INSERT INTO salaries VALUES(10009,85875,'1997-02-15','1998-02-15'); INSERT INTO salaries VALUES(10009,89324,'1998-02-15','1999-02-15'); INSERT INTO salaries VALUES(10009,90668,'1999-02-15','2000-02-15'); INSERT INTO salaries VALUES(10009,93507,'2000-02-15','2001-02-14'); INSERT INTO salaries VALUES(10009,94443,'2001-02-14','2002-02-14');
View Code

 建立dept_emp表格服務器

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`));
View Code

插入dept_emp內容ide

INSERT INTO dept_emp VALUES(10001,'d001','1986-06-26','9999-01-01'); INSERT INTO dept_emp VALUES(10002,'d001','1996-08-03','9999-01-01'); INSERT INTO dept_emp VALUES(10003,'d004','1995-12-03','9999-01-01'); INSERT INTO dept_emp VALUES(10004,'d004','1986-12-01','9999-01-01'); INSERT INTO dept_emp VALUES(10005,'d003','1989-09-12','9999-01-01'); INSERT INTO dept_emp VALUES(10006,'d002','1990-08-05','9999-01-01'); INSERT INTO dept_emp VALUES(10007,'d005','1989-02-10','9999-01-01'); INSERT INTO dept_emp VALUES(10008,'d005','1998-03-11','2000-07-31'); INSERT INTO dept_emp VALUES(10009,'d006','1985-02-18','9999-01-01'); INSERT INTO dept_emp VALUES(10010,'d005','1996-11-24','2000-06-26'); INSERT INTO dept_emp VALUES(10010,'d006','2000-06-26','9999-01-01');
View Code

 建立titles表格函數

CREATE TABLE `titles` (
`emp_no` int(11) NOT NULL,
`title` varchar(50) NOT NULL,
`from_date` date NOT NULL,
`to_date` date NOT NULL);
View Code

插入titles內容測試

INSERT INTO titles VALUES(10001,'Senior Engineer','1986-06-26','9999-01-01'); INSERT INTO titles VALUES(10002,'Staff','1996-08-03','9999-01-01'); INSERT INTO titles VALUES(10003,'Senior Engineer','1995-12-03','9999-01-01'); INSERT INTO titles VALUES(10004,'Engineer','1986-12-01','1995-12-01'); INSERT INTO titles VALUES(10004,'Senior Engineer','1995-12-01','9999-01-01'); INSERT INTO titles VALUES(10005,'Senior Staff','1996-09-12','9999-01-01'); INSERT INTO titles VALUES(10005,'Staff','1989-09-12','1996-09-12'); INSERT INTO titles VALUES(10006,'Senior Engineer','1990-08-05','9999-01-01'); INSERT INTO titles VALUES(10007,'Senior Staff','1996-02-11','9999-01-01'); INSERT INTO titles VALUES(10007,'Staff','1989-02-10','1996-02-11'); INSERT INTO titles VALUES(10008,'Assistant Engineer','1998-03-11','2000-07-31'); INSERT INTO titles VALUES(10009,'Assistant Engineer','1985-02-18','1990-02-18'); INSERT INTO titles VALUES(10009,'Engineer','1990-02-18','1995-02-18'); INSERT INTO titles VALUES(10009,'Senior Engineer','1995-02-18','9999-01-01'); INSERT INTO titles VALUES(10010,'Engineer','1996-11-24','9999-01-01'); INSERT INTO titles VALUES(10010,'Engineer','1996-11-24','9999-01-01');
View Code

建立 departments表格大數據

CREATE TABLE `departments` (
`dept_no` char(4) NOT NULL,
`dept_name` varchar(40) NOT NULL,
PRIMARY KEY (`dept_no`));
View Code

插入departments內容優化

INSERT INTO departments VALUES('d001','Marketing'); INSERT INTO departments VALUES('d002','Finance'); INSERT INTO departments VALUES('d003','Human Resources'); INSERT INTO departments VALUES('d004','Production'); INSERT INTO departments VALUES('d005','Development'); INSERT INTO departments VALUES('d006','Quality Management');
View Code

建立employees表格

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`));
View Code

插入employees內容

INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26'); INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21'); INSERT INTO employees VALUES(10003,'1959-12-03','Parto','Bamford','M','1986-08-28'); INSERT INTO employees VALUES(10004,'1954-05-01','Chirstian','Koblick','M','1986-12-01'); INSERT INTO employees VALUES(10005,'1955-01-21','Kyoichi','Maliniak','M','1989-09-12'); INSERT INTO employees VALUES(10006,'1953-04-20','Anneke','Preusig','F','1989-06-02'); INSERT INTO employees VALUES(10007,'1957-05-23','Tzvetan','Zielinski','F','1989-02-10'); INSERT INTO employees VALUES(10008,'1958-02-19','Saniya','Kalloufi','M','1994-09-15'); INSERT INTO employees VALUES(10009,'1952-04-19','Sumant','Peac','F','1985-02-18'); INSERT INTO employees VALUES(10010,'1963-06-01','Duangkaew','Piveteau','F','1989-08-24'); INSERT INTO employees VALUES(10011,'1953-11-07','Mary','Sluis','F','1990-01-22');
View Code

 

1,查找最晚入職員工的全部信息

SELECT *
FROM employees
ORDER BY hire_date DESC LIMIT 0,1;

 

2,查找入職員工時間排名倒數第三的員工全部信息

SELECT *
FROM employees
ORDER BY hire_date DESC LIMIT 2,1;

 

3,查找當前薪水詳情以及部門編號dept_no

查找各個部門當前(to_date='9999-01-01')領導當前薪水詳情以及其對應部門編號dept_no

錯誤嘗試第二次【緣由:①表的前後出錯;②to_date兩次限定條件】

SELECT d.emp_no,s.salary,s.from_date,s.to_date,d.dept_no
FROM dept_manager AS d
INNER JOIN salaries AS s
ON d.emp_no=s.emp_no
WHERE d.to_date='9999-01-01';

正確語句:

SELECT s.*,d.dept_no
FROM salaries AS s
INNER JOIN dept_manager AS d
ON d.emp_no=s.emp_no
WHERE d.to_date='9999-01-01'
AND s.to_date='9999-01-01';

關於爲何必定要兩個表格的時間都限制成規定時間(9999-01-01)呢?

-----由於薪水錶是按年發的,而題目要查找的是當前的薪水,因此要過濾掉之前,而dept_manager是由於有領導會離職,to_date時間不必定是9999-01-01,因此要過濾過離職的領導
 

4,查找全部已經分配部門的員工的last_name和first_name

錯誤嘗試第二次【緣由查找到:,的中文標點致使的】

SELECT e.last_name,e.first_name,d.dept_no
FROM dept_emp AS d
INNER JOIN employees AS e
ON e.emp_no=d.emp_no;

正確的語句:

SELECT e.last_name,e.first_name,d.dept_no
FROM dept_emp AS d
INNER JOIN employees AS e
ON e.emp_no=d.emp_no;

 

5,查找全部員工的last_name和first_name以及對應部門編號dept_no【LEFT ,RIGHT ,INNER JOIN】

SELECT e.last_name,e.first_name,d.dept_no
FROM employees AS e
LEFT JOIN dept_emp AS d
ON e.emp_no=d.emp_no;

 

6,查找全部員工入職時候的薪水狀況

第二次錯誤嘗試【錯誤緣由:內鏈接條件與WHERE條件混淆】

SELECT e.emp_no,s.salary
FROM employees e
INNER JOIN salaries s
ON e.emp_no=s.emp_no
WHERE e.hire_date=s.to_date
ORDER BY emp_no DESC;

 

正確語句1:【內鏈接完成】

SELECT e.emp_no,s.salary
FROM employees e INNER JOIN salaries s
ON e.emp_no=s.emp_no AND e.hire_date=s.from_date
ORDER BY e.emp_no DESC;

正確語句2:【,號並列鏈接完成】

SELECT e.emp_no, s.salary 
FROM employees AS e, salaries AS s
WHERE e.emp_no = s.emp_no AND e.hire_date = s.from_date
ORDER BY e.emp_no DESC

解析:

內鏈接是取左右兩張表的交集造成一個新表,用FROM並列兩張表後仍然仍是兩張表。

若是還要對新表進行操做則要用內鏈接。從效率上看應該FROM並列查詢比較快,由於不用造成新表。本題從效果上看兩個方法沒區別。

 

7,查找薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t

第二次嘗試錯誤【錯誤緣由:把問題想複雜了】

SELECT s.emp_no,COUNT(s.emp) t
FROM salaries s INNER JOIN salaries s1
ON s.from_date=s1.to_date
GROUP BY emp_no HAVING t>14;

 

正確語句:

SELECT s.emp_no,COUNT(s.emp_no) t
FROM salaries s 
GROUP BY s.emp_no HAVING t>15;

 

注意:

group by與order by有什麼區別,order by就是排序。而group by就是分組,舉個例子好說點,group by 單位名稱 
這樣的運行結果就是以「單位名稱」爲分類標誌統計各單位的職工人數和工資總額。
這樣能夠更好的分下類,更好看一些。
還有就是爲何沒有用where而是用的having,記住下面的兩句話就行了。
WHERE語句在GROUP BY語句以前;SQL會在分組以前計算WHERE語句。   
HAVING語句在GROUP BY語句以後;SQL會在分組以後計算HAVING語句。

 

8,找出全部員工當前薪水salary狀況

找出全部員工當前(to_date='9999-01-01')具體的薪水salary狀況,對於相同的薪水只顯示一次,並按照逆序顯示

SELECT DISTINCT s.salary
FROM salaries s
WHERE s.to_date='9999-01-01'
ORDER BY s.salary DESC;

 

更優化的語句:

SELECT s.salary
FROM salaries s
WHERE s.to_date='9999-01-01'
GROUP BY s.salary
ORDER BY s.salary DESC;

注意:

大部分人都是用distinct,可是大表通常用distinct效率不高,大數據量的時候都禁止用distinct,建議用group by解決重複問題。

簡單一點理解,在單表的時候使用distinct,多表的時候使用group by,雖然通常使用group by ,但仍是要知道distinct的用法

 

9,獲取全部部門當前manager的當前薪水狀況,給出dept_no, emp_no以及salary,當前表示to_date='9999-01-01'

兩表聯查

SELECT d.dept_no,s.emp_no,s.salary
FROM dept_manager d,salaries s
WHERE d.emp_no=s.emp_no
AND s.to_date='9999-01-01'
AND d.to_date='9999-01-01';

內鏈接

SELECT d.dept_no,s.emp_no,s.salary
FROM dept_manager d INNER JOIN salaries s
ON d.emp_no=s.emp_no
WHERE  s.to_date='9999-01-01'
AND d.to_date='9999-01-01';

 

10,獲取全部非manager的員工emp_no

 NOT IN條件限制

SELECT e.emp_no
FROM employees e
WHERE e.emp_no NOT IN(
SELECT d.emp_no
FROM dept_manager d);

 

左鏈接嘗試錯誤【①限定條件問題,應該是全部的dept_no;②應該顯示鏈接後新表的全部內容】

SELECT e.emp_no
FROM employees e LEFT JOIN dept_manager d
ON e.emp_no=d.emp_no
WHERE e.dept_no IS NULL;
SELECT emp_no
FROM (SELECT e.*
FROM employees e LEFT JOIN dept_manager d ON e.emp_no=d.emp_no)
WHERE dept_no IS NULL;

左鏈接正確語句:

SELECT emp_no
FROM (SELECT *
FROM employees LEFT JOIN dept_manager
ON employees.emp_no=dept_manager.emp_no)
WHERE dept_no IS NULL;

 

SQL是支持集合運算的:

SELECT employees.emp_no
FROM employees
EXCEPT
SELECT dept_manager.emp_no
FROM dept_manager;
-- EXPECT  集合差運算【集合A-集合B】
-- UNION  集合並運算【集合A,集合B全部元素組成】
-- INTERSECT 集合交運算【集合A、集合B共有的部分】

 

11,獲取全部員工當前的manager

獲取全部員工當前的manager,若是當前的manager是本身的話結果不顯示,當前表示to_date='9999-01-01'。
結果第一列給出當前員工的emp_no,第二列給出其manager對應的manager_no。

兩表聯查嘗試:【不等號<>更加通用;!=在sql2000中用到,則是語法錯誤,不兼容的】

SELECT de.emp_no,dm.emp_no AS manager_no
FROM dept_emp de ,dept_manager dm
WHERE de.to_date='9999-01-01'
AND dm.to_date='9999-01-01'
AND dm.dept_no=de.dept_no
AND de.emp_no<>dm.emp_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.to_date='9999-01-01'
AND dm.to_date='9999-01-01'
AND de.emp_no != dm.emp_no;

 

12,獲取全部部門中當前員工薪水最高的相關信息

獲取全部部門中當前員工薪水最高的相關信息,給出dept_no, emp_no以及其對應的salary

內鏈接嘗試錯誤:【GROUP BY 這條語句須要本身好好探究一下】

SELECT d.dept_no,d.emp_no,MAX(s.salary) salary
FROM dept_emp 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';

正確語法:

SELECT d.dept_no,s.emp_no,MAX(s.salary) AS salary
FROM salaries AS s INNER JOIN dept_emp AS d
ON d.emp_no=s.emp_no
WHERE d.to_date='9999-01-01'
AND s.to_date='9999-01-01'
GROUP BY d.dept_no;

兩表聯查:

select d.dept_no, d.emp_no, max(s.salary) 
from  salaries s , dept_emp d
where d.emp_no = s.emp_no
and d.to_date='9999-01-01'
and s.to_date='9999-01-01'
group by d.dept_no;

 

我在本身的阿里雲主機上的MySQL還遇到了【ONLY_FULL_GROUP_BY問題】

這個主要是本身MySQL服務器設置中的sql_mode中設置了ONLY_FULL_GROUP_BY致使

解決方法見連接:http://www.javashuo.com/article/p-bigrtvog-k.html

 

用鏈接和用from table1, table2並列查詢,有時候均可以解題。

只是前者將幾張錶鏈接成一張大表,後者是並列查詢若干表,兩種方法在表中數據龐大的狀況下確定有效率的差別,至於哪一個好本身百度一下吧,有實驗環境也能夠本身測試一下。

 13,從titles表獲取按照title進行分組

從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。

SELECT title,COUNT(title) t
FROM titles 
GROUP BY title HAVING t>1;

爲何不用考慮 to_date='9999-01-01' 呢?【關鍵字:當前沒有出現】

以正常邏輯來講要加,不然沒有意義,但題目沒要求,並且加了 to_date='9999-01-01'就通不過了,能夠從測試用例看出題目算的是當前及之前titles的數目總數

 

14,從titles表獲取按照title進行分組,注意對於重複的emp_no進行忽略。

從titles表獲取按照title進行分組,每組個數大於等於2,給出title以及對應的數目t。
注意對於重複的title進行忽略。

本身的錯誤嘗試:

SELECT DISTINCT title,COUNT(*) t
FROM titles
GROUP BY title HAVING t>1;

正確的語句:

SELECT title,COUNT(DISTINCT emp_no) t
FROM titles
GROUP BY title HAVING t>1;

 

15,查找employees表

查找employees表全部emp_no爲奇數,且last_name不爲Mary的員工信息,並按照hire_date逆序排列

SELECT *
FROM employees
WHERE emp_no%2=1
AND last_name<>'Mary'
ORDER BY hire_date DESC;

 

16,統計出當前各個title類型對應的員工當前薪水對應的平均工資

統計出當前各個title類型對應的員工當前(to_date='9999-01-01')薪水對應的平均工資。結果給出title以及平均工資avg。

兩表聯立查詢:

SELECT t.title,AVG(s.salary) avg
FROM salaries s,titles t
WHERE s.emp_no=t.emp_no
AND s.to_date='9999-01-01'
AND t.to_date='9999-01-01'
GROUP BY title;

內鏈接查詢:

SELECT t.title,avg(s.salary)
FROM salaries as s INNER JOIN titles as t
ON s.emp_no = t.emp_no
AND s.to_date = '9999-01-01'
AND t.to_date = '9999-01-01'
GROUP BY title

 

17,獲取當前薪水第二多的員工的emp_no以及其對應的薪水salary

直接查詢:【可是這樣會有一些問題】

SELECT emp_no,salary
FROM salaries
WHERE to_date='9999-01-01'
ORDER BY salary DESC LIMIT 1,1;
避免了2個問題:
(1) 首先這樣能夠解決多我的工資相同的問題;
(2) 另外,篩選出第二多的工資時要注意distinct salary,不然不能選出第二多的工資。
SELECT emp_no, salary 
FROM salaries
WHERE to_date = '9999-01-01' 
AND salary = (
    SELECT DISTINCT salary 
    from salaries 
    ORDER BY salary 
    DESC LIMIT 1,1
);

大數據量的狀況下,避免使用DISTINCT

SELECT emp_no, salary 
FROM salaries
WHERE to_date = '9999-01-01' 
AND salary = (
    SELECT salary 
    from salaries 
    GROUP BY salary
    ORDER BY salary 
    DESC LIMIT 1,1
);

 

18,獲取當前薪水第二多的員工的emp_no以及其對應的薪水salary,不許使用order by

本身嘗試的:

SELECT s.emp_no,MAX(s.salary),e.last_name,e.first_name
FROM employees AS e ,salaries AS s 
WHERE s.emp_no=e.emp_no
AND s.to_date='9999-01-01'
AND e.to_date='9999-01-01'
AND s.salary NOT IN(SELECT MAX(salary) FROM salaries WHERE to_date='9999-01-01');

改正代碼【兩表聯立】:

SELECT s.emp_no,MAX(s.salary),e.last_name,e.first_name
FROM employees AS e ,salaries AS s 
WHERE s.emp_no=e.emp_no
AND s.to_date='9999-01-01'
AND s.salary NOT IN(SELECT MAX(salary) FROM salaries WHERE to_date='9999-01-01');

正確語句【內鏈接】:

SELECT e.emp_no, MAX(s.salary) AS salary, e.last_name, e.first_name 
FROM employees AS e INNER JOIN salaries AS s 
ON e.emp_no = s.emp_no
WHERE s.to_date = '9999-01-01'
AND s.salary NOT IN (SELECT MAX(salary) FROM salaries WHERE to_date = '9999-01-01')

 

19,查找全部員工的last_name和first_name以及對應的dept_name

查找全部員工的last_name和first_name以及對應的dept_name,也包括暫時沒有分配部門的員工【LEFT,RIGHT JOIN眉頭一緊發現關鍵所在】

本身嘗試

SELECT  t.last_name,t.first_name,dm.dept_name
FROM departments dm ,(
    SELECT e.last_name,e.first_name,de.* 
    FROM employees e LEFT JOIN dept_emp de
    ON e.emp_no=de.emp_no) t
WHERE t.dept_no=dm.dept_no;

正確的語句:

SELECT  e.last_name,e.first_name,dm.dept_name
FROM (employees e LEFT JOIN dept_emp de ON e.emp_no=de.emp_no) 
LEFT JOIN departments dm 
ON de.dept_no=dm.dept_no;

 

20,查找員工編號emp_no爲10001其自入職以來的薪水salary漲幅值growth

分別查找兩個to_date的數據相減

SELECT ((SELECT salary
FROM salaries
WHERE emp_no=10001
AND to_date='9999-01-01')-
(SELECT salary
FROM salaries
WHERE emp_no=10001
ORDER BY to_date LIMIT 0,1)) AS growth;

 

21,查找全部員工自入職以來的薪水漲幅狀況【全部員工】【聯查與鏈接如何區分使用???】

嘗試使用上面的方法進行解決問題【ERROR 1242 (21000): Subquery returns more than 1 row】

SELECT ((SELECT salary
FROM salaries
WHERE to_date='9999-01-01')-
(SELECT salary
FROM salaries
ORDER BY to_date LIMIT 0,1)) AS growth;

正確語句:

SELECT sCurrent.emp_no, (sCurrent.salary-sStart.salary) AS growth
FROM (SELECT s.emp_no, s.salary FROM employees e, salaries s WHERE e.emp_no = s.emp_no AND s.to_date = '9999-01-01') AS sCurrent,
(SELECT s.emp_no, s.salary FROM employees e, salaries s WHERE e.emp_no = s.emp_no AND s.from_date = e.hire_date) AS sStart
WHERE sCurrent.emp_no = sStart.emp_no
ORDER BY growth

 

 22,統計各個部門對應員工漲幅的次數總和

 統計各個部門對應員工漲幅的次數總和,給出部門編碼dept_no、部門名稱dept_name以及次數sum

本身手撕出來的

SELECT dm.dept_no,dm.dept_name,dc.num
FROM (SELECT de.dept_no,SUM(sc.sSum) AS num
FROM dept_emp de INNER JOIN (SELECT s.emp_no,COUNT(s.emp_no) AS sSum FROM salaries s GROUP BY s.emp_no) sc
ON de.emp_no=sc.emp_no
GROUP BY de.dept_no) dc,departments dm
WHERE dc.dept_no=dm.dept_no;

分級進行處理:

①統計各個員工漲薪次數  COUNT

SELECT s.emp_no,COUNT(s.emp_no) AS sSum
FROM salaries s
GROUP BY s.emp_no;

②統計各個部門的漲薪次數  SUM

SELECT de.dept_no,SUM(sc.sSum) AS num
FROM dept_emp de INNER JOIN (SELECT s.emp_no,COUNT(s.emp_no) AS sSum FROM salaries s GROUP BY s.emp_no) sc
ON de.emp_no=sc.emp_no
GROUP BY de.dept_no;

③將departments聯查顯示部門名稱

SELECT dm.dept_no,dm.dept_name,dc.num
FROM (SELECT de.dept_no,SUM(sc.sSum) AS num
FROM dept_emp de INNER JOIN (SELECT s.emp_no,COUNT(s.emp_no) AS sSum FROM salaries s GROUP BY s.emp_no) sc
ON de.emp_no=sc.emp_no
GROUP BY de.dept_no) dc,departments dm
WHERE dc.dept_no=dm.dept_no;

 

 23,對全部員工的薪水按照salary進行按照1-N的排名【兩表聯查】

對全部員工的當前(to_date='9999-01-01')薪水按照salary進行按照1-N的排名,相同salary並列且按照emp_no升序排列

SELECT s1.emp_no, s1.salary, COUNT(DISTINCT s2.salary) AS rank
FROM salaries AS s1, salaries AS s2
WHERE s1.to_date = '9999-01-01'  AND s2.to_date = '9999-01-01' AND s1.salary <= s2.salary
GROUP BY s1.emp_no
ORDER BY s1.salary DESC, s1.emp_no ASC

 

24,獲取全部非manager員工當前的薪水狀況

獲取全部非manager員工當前的薪水狀況,給出dept_no、emp_no以及salary ,當前表示to_date='9999-01-01'

SELECT de.dept_no,de.emp_no,es.salary
FROM dept_emp de , (SELECT e.emp_no,s.salary
FROM salaries s INNER JOIN employees e
ON s.emp_no=e.emp_no
WHERE s.to_date='9999-01-01'
AND e.emp_no NOT IN (SELECT emp_no FROM dept_manager)) es
WHERE de.emp_no=es.emp_no;

分級來進行處理:

①內鏈接salaries與employees,找出當前員工的工號與工資

SELECT e.emp_no,s.salary
FROM salaries s INNER JOIN employees e
ON s.emp_no=e.emp_no
WHERE s.to_date='9999-01-01'

②在上面的基礎上加上一個語句,去除管理崗的工號

SELECT e.emp_no,s.salary
FROM salaries s INNER JOIN employees e
ON s.emp_no=e.emp_no
WHERE s.to_date='9999-01-01'
AND e.emp_no NOT IN (SELECT emp_no FROM dept_manager);

③將新表與dept_emp進行聯查處理

SELECT de.dept_no,de.emp_no,es.salary
FROM dept_emp de , (SELECT e.emp_no,s.salary
FROM salaries s INNER JOIN employees e
ON s.emp_no=e.emp_no
WHERE s.to_date='9999-01-01'
AND e.emp_no NOT IN (SELECT emp_no FROM dept_manager)) es
WHERE de.emp_no=es.emp_no;

 

正確語句2:本質上是同樣的

SELECT de.dept_no, s.emp_no, s.salary 
FROM (employees AS e INNER JOIN salaries AS s ON s.emp_no = e.emp_no AND s.to_date = '9999-01-01')
INNER JOIN dept_emp AS de ON e.emp_no = de.emp_no
WHERE de.emp_no NOT IN (SELECT emp_no FROM dept_manager WHERE to_date = '9999-01-01')

 

25,獲取員工其當前的薪水比其manager當前薪水還高的相關信息【兩表聯查】

獲取員工其當前的薪水比其manager當前薪水還高的相關信息,當前表示to_date='9999-01-01',
結果第一列給出員工的emp_no,
第二列給出其manager的manager_no,
第三列給出該員工當前的薪水emp_salary,
第四列給該員工對應的manager當前的薪水manager_salary

SELECT sem.emp_no AS emp_no, sdm.emp_no AS manager_no, sem.salary AS emp_salary, sdm.salary AS manager_salary
FROM (SELECT s.salary, s.emp_no, de.dept_no FROM salaries s INNER JOIN dept_emp de
ON s.emp_no = de.emp_no AND s.to_date = '9999-01-01' ) AS sem, 
(SELECT s.salary, s.emp_no, dm.dept_no FROM salaries s INNER JOIN dept_manager dm
ON s.emp_no = dm.emp_no AND s.to_date = '9999-01-01' ) AS sdm
WHERE sem.dept_no = sdm.dept_no AND sem.salary > sdm.salary

分級來進行處理:

①先內鏈接salaries與dept_emp,獲取當前工資、工號、部門號;

SELECT s.salary, s.emp_no, de.dept_no 
FROM salaries s INNER JOIN dept_emp de 
ON s.emp_no=de.emp_no 
AND s.to_date = '9999-01-01')

②先內鏈接salaries與dept_manager,獲取當前工資、工號、部門號;

SELECT s.salary, s.emp_no, dm.dept_no 
FROM salaries s INNER JOIN dept_manager dm 
ON s.emp_no=dm.emp_no 
AND s.to_date = '9999-01-01')

③將兩個表聯查限制條件是:同一個部門,非管理比管理工資高;

SELECT sem.emp_no,sdm.emp_no manager_no,sem.salary emp_salary,sdm.salary emp_salary
FROM (SELECT s.salary, s.emp_no, de.dept_no FROM salaries s INNER JOIN dept_emp de ON s.emp_no=de.emp_no AND s.to_date = '9999-01-01') sem,
(SELECT s.salary, s.emp_no, dm.dept_no FROM salaries s INNER JOIN dept_manager dm ON s.emp_no=dm.emp_no AND s.to_date = '9999-01-01') sdm
WHERE sem.dept_no=sdm.dept_no AND sem.salary > sdm.salary;

26,彙總各個部門當前員工的title類型的分配數目

彙總各個部門當前員工的title類型的分配數目,結果給出部門編號dept_no、dept_name、其當前員工全部的title以及該類型title對應的數目count

錯誤語句:

SELECT dm.dept_no,dm.dept_name,ec.title,COUNT(ec.title) 'count'
FROM departments dm,(SELECT DISTINCT de.emp_no,de.dept_no,t.title
FROM dept_emp de INNER JOIN titles t
ON de.emp_no=t.emp_no
WHERE de.to_date='9999-01-01'
AND t.to_date='9999-01-01') ec
WHERE dm.dept_no=ec.dept_no
GROUP BY dm.dept_no;

 

 正確語句:

SELECT de.dept_no, dp.dept_name, t.title, COUNT(t.title) AS count
FROM titles AS t INNER JOIN dept_emp AS de 
ON t.emp_no = de.emp_no AND de.to_date = '9999-01-01' AND t.to_date = '9999-01-01'
INNER JOIN departments AS dp 
ON de.dept_no = dp.dept_no
GROUP BY de.dept_no, t.title

 

 27,給出每一個員工每一年薪水漲幅超過5000的員工編號emp_no【新知識點】

  給出每一個員工每一年薪水漲幅超過5000的員工編號emp_no、薪水變動開始日期from_date以及薪水漲幅值salary_growth,並按照salary_growth逆序排列。

  提示:在sqlite中獲取datetime時間對應的年份函數爲strftime('%Y', to_date)【難度優勢大】

SELECT s2.emp_no, s2.from_date, (s2.salary - s1.salary) AS salary_growth
FROM salaries AS s1, salaries AS s2
WHERE s1.emp_no = s2.emp_no 
AND salary_growth > 5000
AND (strftime("%Y",s2.to_date) - strftime("%Y",s1.to_date) = 1 
     OR strftime("%Y",s2.from_date) - strftime("%Y",s1.from_date) = 1 )
ORDER BY salary_growth DESC

 

 

總結

經常使用語句:SELECT,FROM,WHERE【基礎】

關鍵知識點:

疑難知識點:

  1. INNER,LEFT,RIGHT JOIN 
  2. ORDER BY
  3. DISTICT 大數據時,該語句效率很低,建議使用GROUP BY 去重
  4. GROUP BY,HAVING
  5. COUNT
  6. MAX,AVG
  7. EXCEPT,UNION,INTERSECT
  8. 在sqlite中獲取datetime時間對應的年份函數爲strftime('%Y', to_date)
相關文章
相關標籤/搜索