數據庫SQL實戰全解

前言

最開始寫SQL題全解的初衷是博主校招提前批時被pdd的筆試SQL一頓虐,斷斷續續花了一些時間也算是把所有的題目全部做完了。

1.查找最晚入職員工的所有信息

select * from employees
where hire_date=
(select max(hire_date) from employees);

2.查找入職員工時間排名倒數第三的員工所有信息

select * from employees
where hire_date=
(select distinct hire_date from employees order by hire_date desc limit 2,1);

要點:

# LIMIT m,n : 表示從第m+1條開始,取n條數據;
# LIMIT n : 表示從第0條開始,取n條數據,是limit(0,n)的縮寫

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

SELECT s.*, d.dept_no
FROM salaries s , dept_manager d
WHERE s.to_date=‘9999-01-01’
AND d.to_date=s.to_date
AND s.emp_no = d.emp_no;

4.查找所有已經分配部門的員工的last_name和first_name

select last_name,first_name,dept_no
from employees e,dept_emp d
where e.emp_no=d.emp_no;
或者
select last_name,first_name,dept_no
from employees e inner join dept_emp d
on e.emp_no=d.emp_no;

5.查找所有員工的last_name和first_name以及對應部門編號dept_no,也包括展示沒有分配具體部門的員工

注意:因爲這裏有些 展示包括沒有分配具體部門的員工,所以 這裏用左連接

select last_name,first_name,dept_no
from employees e left join dept_emp d
on e.emp_no=d.emp_no;

6.查找所有員工入職時候的薪水情況,給出emp_no以及salary, 並按照emp_no進行逆序

select e.emp_no,salary
from salaries s,employees e
where s.emp_no=e.emp_no and s.from_date=e.hire_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 可以省略

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

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

select emp_no, count(salary) as t
from salaries
group by emp_no
having t>15;
注意:由於COUNT()函數不可用於WHERE語句中,故使用HAVING語句來限定t>15的條件

8.找出所有員工當前(to_date=‘9999-01-01’)具體的薪水salary情況,對於相同的薪水只顯示一次,並按照逆序顯示

select distinct salary
from salaries
where to_date=‘9999-01-01’
order by salary desc;

9.獲取所有部門當前manager的當前薪水情況,給出dept_no, emp_no以及salary,當前表示to_date=‘9999-01-01’

select d.dept_no,d.emp_no,salary
from dept_manager d,salaries s
where d.emp_no=s.emp_no and s.to_date=‘9999-01-01’ and s.to_date=d.to_date;

10.獲取所有非manager的員工emp_no

1.查詢不在dept_manager中的emp_no

select emp_no from employees
where emp_no not in (select emp_no from dept_manager);

2.左連接 得到 dept_no爲空的數據

select e.emp_no from employees e #這裏emp_no必須加上e. 表示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 e left join dept_manager d on e.emp_no=d.emp_no)
where dept_no is null;

11.獲取所有員工當前的manager,如果當前的manager是自己的話結果不顯示,當前表示to_date=‘9999-01-01’。

結果第一列給出當前員工的emp_no,第二列給出其manager對應的manager_no。
select e.emp_no, m.emp_no as manager_no
from dept_emp e inner join dept_manager m on e.dept_no=m.dept_no
where e.to_date=m.to_date and m.to_date=‘9999-01-01’ and e.emp_no not in
(select emp_no from dept_manager);
或者
select e.emp_no, m.emp_no as manager_no
from dept_emp e inner join dept_manager m on e.dept_no=m.dept_no and e.to_date=m.to_date and m.to_date=‘9999-01-01’
where e.emp_no not in (select emp_no from dept_manager);

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

select dept_no,s.emp_no,max(salary) as salary #emp_no這裏必須加上s.前綴 不然會報語法出錯
from dept_emp d ,salaries s
where d.emp_no=s.emp_no and d.to_date=s.to_date and s.to_date=‘9999-01-01’
group by dept_no;

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

select title,count(*) as t
from titles group by title having t>=2;

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

  注意對於重複的emp_no進行忽略。

select title,count(distinct emp_no) as t
from titles group by title having t>=2;

15.查找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類型對應的員工當前(to_date=‘9999-01-01’)薪水對應的平均工資。結果給出title以及平均工資avg。

select title, avg(salary) as avg
from titles t,salaries s
where t.emp_no=s.emp_no and t.to_date=s.to_date and s.to_date=‘9999-01-01’
group by title;

17.獲取當前(to_date=‘9999-01-01’)薪水第二多的員工的emp_no以及其對應的薪水salary

select emp_no,salary
from salaries where to_date=‘9999-01-01’
order by salary desc limit 1,1;

18.查找當前薪水(to_date=‘9999-01-01’)排名第二多的員工編號emp_no、薪水salary、last_name以及first_name,不準使用order by

注意:既然不能用order by,那麼只能嵌套select子查詢 用兩次max函數 輸出次最大

select e.emp_no, max(salary) as salary,last_name,first_name
from employees e, salaries s
where e.emp_no=s.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’
);

19.查找所有員工的last_name和first_name以及對應的dept_name,也包括暫時沒有分配部門的員工

注意 也包括暫時沒有分配部門的員工 說明要用左連接

select last_name,first_name,dept_name
from employees e left join dept_emp p on p.emp_no=e.emp_no --dept_emp放在三張表中間 都用left join
left join departments d on p.dept_no=d.dept_no;

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

注意:薪水錶中的主鍵是emp_no和from_date 也就是會出現許多相同emp_no的行

select(
(select salary from salaries where emp_no=10001 order by to_date desc limit 1)-
(select salary from salaries where emp_no=10001 order by from_date limit 1) --默認升序
) as growth;

21.查找所有員工自入職以來的薪水漲幅情況,給出員工編號emp_no以及其對應的薪水漲幅growth,並按照growth進行升序

這道題有點難 入職以來 當前時間(‘9999-01-01’)的工資減去入職當天(s.from_date=e.hire_date)

select sCurrent.emp_no,(sCurrent.salary-sStart.salary) as growth
from
(select s.emp_no,s.salary from employees e inner join salaries s on e.emp_no=s.emp_no and s.to_date=‘9999-01-01’) as sCurrent
inner join
(select s.emp_no,s.salary from employees e inner join salaries s on e.emp_no=s.emp_no and s.from_date=e.hire_date) as sStart
on sCurrent.emp_no=sStart.emp_no
order by growth;

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

注意,如果按照嚴格意義來寫 會比較難,題目中的樣例是隻要出現一條記錄就算漲幅 ,salary相同漲幅爲0 salary變少理解爲漲幅爲負

select d.dept_no,d.dept_name, count(s.salary) as sum
from departments d inner join dept_emp de on d.dept_no=de.dept_no
inner join salaries s on de.emp_no=s.emp_no
group by d.dept_no;

23.對所有員工的當前(to_date=‘9999-01-01’)薪水按照salary進行按照1-N的排名,相同salary並列且按照emp_no升序排列

這道題難!! 需要複用salaries進行排名

以下解析 來自大佬解析:
1、從兩張相同的salaries表(分別爲s1與s2)進行對比分析,先將兩表限定條件設爲to_date = ‘9999-01-01’,挑選出當前所有員工的薪水情況。
2、本題的精髓在於 s1.salary <= s2.salary,意思是在輸出s1.salary的情況下,有多少個s2.salary大於等於s1.salary,比如當s1.salary=94409時,有3個s2.salary(分別爲94692,94409,94409)大於等於它,但由於94409重複,利用COUNT(DISTINCT s2.salary)去重可得工資爲94409的rank等於2。其餘排名以此類推。
3、千萬不要忘了GROUP BY s1.emp_no,否則輸出的記錄只有一條(可能是第一條或者最後一條,根據不同的數據庫而定),因爲用了合計函數COUNT()
4、最後先以 s1.salary 逆序排列,再以 s1.emp_no 順序排列輸出結果
SELECT s1.emp_no, s1.salary, COUNT(DISTINCT s2.salary) AS rank --這裏rank的排名是 1 2 2 3,如果是1 2 2 4則s2.salary前面不加distinct
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員工當前的薪水情況,給出dept_no、emp_no以及salary,當前表示to_date=‘9999-01-01’

select de.dept_no,de.emp_no,salary
from dept_emp de inner join salaries s on de.emp_no=s.emp_no and s.to_date=‘9999-01-01’
where de.emp_no not in (select emp_no from dept_manager);

25.獲取員工其當前的薪水比其manager當前薪水還高的相關信息,當前表示to_date=‘9999-01-01’,

結果第一列給出員工的emp_no,
第二列給出其manager的manager_no,
第三列給出該員工當前的薪水emp_salary,
第四列給該員工對應的manager當前的薪水manager_salary

解題思路:這道題難
本題主要思想是創建兩張表(一張記錄當前所有員工的工資,另一張只記錄部門經理的工資)進行比較,具體思路如下:
1、先用INNER JOIN連接salaries和demp_emp,建立當前所有員工的工資記錄sem
2、再用INNER JOIN連接salaries和demp_manager,建立當前所有經理的工資記錄sdm
3、最後用限制條件sem.dept_no = sdm.dept_no AND sem.salary > sdm.salary找出同一部門中工資比經理高的員工,
並根據題意依次輸出emp_no、manager_no、emp_salary、manager_salary
select des.emp_no,dms.emp_no as manager_no,des.salary as emp_salary, dms.salary as manager_salary
from(
select de.emp_no,de.dept_no,s.salary from dept_emp de inner join salaries s on de.emp_no=s.emp_no where de.to_date=s.to_date and s.to_date=‘9999-01-01’) des,
(select dm.emp_no,dm.dept_no,s.salary from dept_manager dm inner join salaries s on dm.emp_no=s.emp_no where dm.to_date=s.to_date and s.to_date=‘9999-01-01’) dms
where des.dept_no=dms.dept_no and des.salary>dms.salary;

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

select d.dept_no,d.dept_name,t.title, count(t.title) as count
from departments d inner join dept_emp de on d.dept_no=de.dept_no
inner join titles t on de.emp_no=t.emp_no where t.to_date=de.to_date and de.to_date=‘9999-01-01’
group by d.dept_no,d.dept_name,t.title
–這裏以查詢出的前三列交集作爲分組條件

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

提示:在sqlite中獲取datetime時間對應的年份函數爲strftime(’%Y’, to_date)

注意:這裏的題幹條件是每年 需要用到表的自身join 難!!!

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
– 這道題最大的難點在於如何去理解每年增幅
– s1是漲薪水前的表,s2是漲薪水後的表,因爲每個員工漲薪水的時間不全固定,有可能一年漲兩次,有可能兩年漲一次,
– 所以每年薪水的漲幅,應該理解爲兩條薪水記錄的from_date相同或to_date相同。
– 這道題有歧義 2016-12-31與2017-01-01也能算一年增幅嗎??

28.查找描述信息中包括robot的電影對應的分類名稱以及電影數目,而且還需要該分類對應電影數量>=5部

注意:包含robot 使用模糊查詢like %robot%

– 這題的關鍵在於 查詢條件的後半句該分類對應電影數量>=5部,這裏需要按組劃分進行having組過濾
SELECT c.name, COUNT(fc.film_id) FROM
(select category_id, COUNT(film_id) FROM film_category
GROUP BY category_id HAVING count(film_id)>=5) cc,
film f, film_category fc, category c
WHERE f.description LIKE ‘%robot%’
AND f.film_id = fc.film_id
AND c.category_id = fc.category_id
AND c.category_id=cc.category_id

29.使用join查詢方式找出沒有分類的電影id以及名稱

select f.film_id,f.title
from film f left join film_category fc
on f.film_id=fc.film_id where fc.category_id is null;

30.使用子查詢的方式找出屬於Action分類的所有電影對應的title,description

select f.title,f.description from film as f
where f.film_id in
(select fc.film_id from film_category as fc
where fc.category_id in
(select c.category_id from category as c
where c.name = ‘Action’));

31.獲取select對應的執行計劃

Explain select * from employees;

32.將employee表的所有員工的last_name和first_name拼接起來作爲Name

注意:不同數據庫連接字符串的方法不完全相同,MySQL、SQL Server、Oracle等數據庫支持CONCAT方法,

而本題所用的SQLite數據庫只支持用連接符號"||"來連接字符串

SELECT last_name||" "||first_name AS Name FROM employees;
在MySQL中可以使用:select CONCAT(last_name,space(1),first_name) as Name from employees;

33.創建一個act表

CREATE TABLE if not exists actor
(
actor_id smallint(5) NOT NULL ,
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL,
last_update timestamp NOT NULL DEFAULT (datetime(‘now’,‘localtime’)), – ,
PRIMARY KEY(actor_id)
)

34.批量插入數據

INSERT INTO actor
VALUES (1, ‘PENELOPE’, ‘GUINESS’, ‘2006-02-15 12:34:33’),
(2, ‘NICK’, ‘WAHLBERG’, ‘2006-02-15 12:34:33’)

35.批量插入數據,如果數據已存在,請忽略,不使用replace操作

牛客的編譯器是sqlite3,答案如下:
insert or ignore into actor
values(3,‘ED’,‘CHASE’,‘2006-02-15 12:34:33’);

36.創建一個actor_name表

create table actor_name as
select first_name,last_name from actor;

37.對first_name創建唯一索引

CREATE UNIQUE INDEX uniq_idx_firstname ON actor(first_name);
CREATE INDEX idx_lastname ON actor(last_name);

38.針對actor表創建視圖

CREATE VIEW actor_name_view AS
SELECT first_name AS first_name_v, last_name AS last_name_v
FROM actor;

39.針對salaries表emp_no字段創建索引idx_emp_no,查詢emp_no爲10005, 使用強制索引。

SQLite中,使用 INDEXED BY 語句進行強制索引查詢,可參考:
SELECT * FROM salaries INDEXED BY idx_emp_no WHERE emp_no = 10005
MySQL中,使用 FORCE INDEX 語句進行強制索引查詢,可參考:
SELECT * FROM salaries FORCE INDEX idx_emp_no WHERE emp_no = 10005

40.在last_update後面增加一列名字create_date

alter table actor add create_date datetime not null default ‘0000-00-00 00:00:00’

41.構造一個觸發器audit_log

構造觸發器時注意以下幾點:
1、用 CREATE TRIGGER 語句構造觸發器,用 BEFORE或AFTER 來指定在執行後面的SQL語句之前或之後來觸發TRIGGER
2、觸發器執行的內容寫出 BEGIN與END 之間
3、可以使用 NEW與OLD 關鍵字訪問觸發後或觸發前的employees_test表單記錄
CREATE TRIGGER audit_log AFTER INSERT ON employees_test
BEGIN
INSERT INTO audit VALUES (NEW.ID, NEW.NAME); --new 關鍵字表示更新後的表的字段 ,old表示更新前的表的字段
END;

42.刪掉emp_no重複的記錄,只保留最小的id對應的記錄

先找到最最小id的記錄,然後刪除操作時做過濾判斷
DELETE FROM titles_test WHERE id NOT IN
(SELECT MIN(id) FROM titles_test GROUP BY emp_no);

43.將所有to_date爲9999-01-01的全部更新爲NULL,且 from_date更新爲2001-01-01。

update titles_test set to_date=null where to_date=‘9999-01-01’;
update titles_test set from_date=‘2001-01-01’;

44.將id=5以及emp_no=10001的行數據替換成id=5以及emp_no=10005,其他數據保持不變,使用replace實現。

運用REPLACE(X,Y,Z)函數。其中X是要處理的字符串,Y是X中將要被替換的字符串,
Z是用來替換Y的字符串,最終返回替換後的字符串。
以下語句用 UPDATE和REPLACE 配合完成,用REPLACE函數替換後的新值複製給 id=5 的 emp_no。
REPLACE的參數爲整型時也可通過。可參考:
UPDATE titles_test SET emp_no = REPLACE(emp_no,10001,10005) WHERE id = 5;

45.將titles_test表名修改爲titles_2017

ALTER TABLE titles_test RENAME TO titles_2017;

46.在audit表上創建外鍵約束,其emp_no對應employees_test表的主鍵id。

mysql中:
alter table audit
add foreign key(emp_no) references employees_test(id);

這裏的OJ系統採用的時sqlite:
由於SQLite中不能通過 ALTER TABLE … ADD FOREIGN KEY … REFERENCES …
語句來對已創建好的字段創建外鍵,因此只能先刪除表,再重新建表的過程中創建外鍵。可參考:
DROP TABLE audit;
CREATE TABLE audit(
EMP_no INT NOT NULL,
create_date datetime NOT NULL,
FOREIGN KEY(EMP_no) REFERENCES employees_test(ID));

47.如何獲取emp_v和employees有相同的數據no

SELECT em.* FROM employees AS em, emp_v AS ev WHERE em.emp_no = ev.emp_no

48.將所有獲取獎金的員工當前的薪水增加10%

UPDATE salaries SET salary = salary * 1.1 WHERE emp_no IN
(SELECT s.emp_no FROM salaries AS s INNER JOIN emp_bonus AS eb
ON s.emp_no = eb.emp_no AND s.to_date = ‘9999-01-01’);

49.針對庫中的所有表生成select count(*)對應的SQL語句

sqlite中的寫法:
select “select count(*) from “||name||”;” as cnts
from sqlite_master
where type=‘table’;

MySQl中的寫法:
select concat(“select count(*) from “,” “,table_name,”;”) as cnts
from (select table_name from information_schema.tables) as new;

50.將employees表中的所有員工的last_name和first_name通過(’)連接起來。

sqlite:
SELECT last_name || “’” || first_name FROM employees;
mysql:
select concat(last_name,"’",first_name) from employees;

51.查找字符串’10,A,B’ 中逗號’,'出現的次數cnt。

SELECT
length( ‘10,A,B’) - length(REPLACE( ‘10,A,B’,’,’,’’));
解題思路:
1.通過length函數獲得字符串的長度:length( ‘10,A,B’)
2.通過replace函數,用空字符替代掉所求字符,並獲得替代後的字符串長度: length(REPLACE( ‘10,A,B’,’,’,’’)
3.兩者相減,獲得所求字符出現的次數:length( ‘10,A,B’) - length(REPLACE( ‘10,A,B’,’,’,’’));

52.獲取Employees中的first_name,查詢按照first_name最後兩個字母,按照升序進行排列

select first_name from employees
order by substr(first_name,length(first_name)-1,2)

substr(字符串,起始位置,長度)
起始位置:截取的子串的起始位置(注意:字符串的第一個字符的索引是1)。值爲正時從字符串開始位置 開始計數,值爲負時從字符串結尾位置開始計數。
長度:截取子串的長度

53.按照dept_no進行彙總,屬於同一個部門的emp_no按照逗號進行連接,結果給出dept_no以及連接出的結果employees

sqlite:
SELECT dept_no, group_concat(emp_no) AS employees
FROM dept_emp GROUP BY dept_no;
MySQL:
select dept_no,group_concat(emp_no SEPARATOR ‘,’)
from dept_emp group by dept_no;

54.查找排除當前最大、最小salary之後的員工的平均工資avg_salary。

SELECT AVG(salary) AS avg_salary FROM salaries
WHERE to_date = ‘9999-01-01’
AND salary NOT IN (SELECT MAX(salary) FROM salaries)
AND salary NOT IN (SELECT MIN(salary) FROM salaries);

55.分頁查詢employees表,每5行一頁,返回第2頁的數據

select * from employees limit 5,5;

56.獲取所有員工的emp_no、部門編號dept_no以及對應的bonus類型btype和received ,沒有分配具體的員工不顯示

SELECT em.emp_no, de.dept_no, eb.btype, eb.recevied
FROM employees AS em INNER JOIN dept_emp AS de
ON em.emp_no = de.emp_no
LEFT JOIN emp_bonus AS eb
ON de.emp_no = eb.emp_no;

57.使用含有關鍵字exists查找未分配具體部門的員工的所有信息。

SELECT * FROM employees WHERE NOT EXISTS
(SELECT emp_no FROM dept_emp WHERE emp_no = employees.emp_no);
這裏還可以用not in(表示不包含):
select * from employees where emp_no not in(select emp_no from dept_emp);

58與47 重複

59.獲取有獎金的員工相關信息。

本題主要考查 SQLite 中 CASE 表達式的用法。
即當 btype = 1 時,得到 salary * 0.1;
當 btype = 2 時,得到 salary * 0.2;
其他情況得到 salary * 0.3。詳細用法請參考:
SELECT e.emp_no, e.first_name, e.last_name, b.btype, s.salary,
(CASE b.btype
WHEN 1 THEN s.salary * 0.1
WHEN 2 THEN s.salary * 0.2
ELSE s.salary * 0.3 END) AS bonus
FROM employees AS e INNER JOIN emp_bonus AS b ON e.emp_no = b.emp_no
INNER JOIN salaries AS s ON e.emp_no = s.emp_no AND s.to_date = ‘9999-01-01’;

60.按照salary的累計和running_total,其中running_total爲前兩個員工的salary累計和,其他以此類推。

  1. 使用窗口函數:
    SELECT emp_no,salary,
    SUM(salary) OVER (ORDER BY emp_no) AS running_total
    FROM salaries
    WHERE to_date = ‘9999-01-01’;

2.把所有小於等於當前編號的表s1和當前編號表s2聯立起來,然後按照當前編號分組,計算出所有小於等於
當前標號的工資總數
SELECT s2.emp_no,s2.salary,SUM(s1.salary) AS running_total
FROM salaries AS s1 INNER JOIN salaries AS s2
ON s1.emp_no <= s2.emp_no
WHERE
s1.to_date = “9999-01-01”
AND s2.to_date = “9999-01-01”
GROUP BY s2.emp_no;

61.對於employees表,在對first_name進行排名後,選出奇數排名對應的first_name

1、本題用到了三層 SELECT 查詢,爲了便於理解,採用縮進方式分層,且最外層對應e1,最內層對應e3;
2、在e3層中,採用 COUNT() 函數對 e2.first_name 進行排名標號,即在給定 e2.first_name的情況下,不大於 e2.first_name 的 e3.first_name 的個數有多少,該個數剛好與 e2.first_name 的排名標號匹配,且將該值命名爲 rowid;
/注意:排名標號後並未排序,即[Bob, Carter, Amy]的排名是[2,3,1],選取奇數排名後輸出[Carter, Amy],所以可見參考答案中的first_name並未按字母大小排序/
3、在e1層中,直接在限定條件 e1.rowid % 2 = 1 下,代表奇數行的 rowid,選取對應的 e1.first_name;
4、e2層則相當於連接e1層(選取表示層)與e3層(標號層)的橋樑。
SELECT e1.first_name FROM
(SELECT e2.first_name,
(SELECT COUNT(*) FROM employees AS e3
WHERE e3.first_name <= e2.first_name)
AS rowid FROM employees AS e2) AS e1
WHERE e1.rowid % 2 = 1;
執行順序: e3->e2->e1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章