国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數據庫 > MySQL > 正文

MYSQL基礎上機練習題(六) 排序問題綜合應用

2024-07-24 12:59:42
字體:
來源:轉載
供稿:網友

一、實驗目的:

各種排序問題的綜合應用

二、實驗內容:

對MySQL基礎上機練習題(二)中所輸入的數據進行排序

三、題目:

1.對全部員工根據薪酬水平進行排序

(1)薪酬水平相同時,按照姓名排序
(2)薪酬水平相同時,排位相同,但不占位排序
(3)薪酬水平相同時,排位相同且占位排序

2.查詢每一個部門排名前三的工作年限

3.查詢每一個部門的排名前三的工薪水平(不同員工同一薪資,只顯示一位)

四、內容:

1.對全部員工根據薪酬水平進行從高到低排序

拿數組(56,56,67,67,67,78,79,80)來說,可以形成三種排列: (1)即使值相同,也會不會排在同一位:(1,2,3,4,5,6,7,8,) (2)值相同的在同一位,但不占位:(1,1,2,2,2,3,4,5) (3)值相同的在同一位,但占位:(1,1,3,3,3,6,7,8)

(1)薪酬水平相同時,按照員工工號排序
Select EmployeeID, InCome, @rowNum := @rowNum+1 AS Rank FROM (SELECT @rowNum := 0)r, Salary ORDER BY InCome DESC

這里的@rowNum 是自定義的一個變量,@rowNum := @rowNum+1 代表一個首項為0,等差為1的自增列r,每查詢到一個InCome(即薪水),就會@rowNum這個變量就會遞增1,放到r這個自增列中。 也可以簡單地把(SELECT @rowNum := 0)r看成是一個新的表,整體的查詢相當于在Salary這個原來的表與新的r表進行復合表查詢 但使用這種方法,在遇到薪酬水平相同時,會出現排位不相同的現象 Mysql排序

如圖中第一名與第二名的薪水相同但排名不一致

(2)薪酬水平相同時,排位相同,但不占位排序

當需要對相同值進行相同排序時,可以使用多一個變量來使得相同薪酬水平的人排位是一致的

SELECT EmployeeID, InCome, @rowNum := @rowNum + (@PRev <> (@prev := InCome)) RankFROM Salary, (SELECT @rowNum := 0, @prev := -1) initORDER BY InCome desc

這里的@prev變量是用作對比前一個InCome和下一個InCome是否一致,(@prev <>(@prev:=InCome))的作用在于判斷是否需要給@rowNum遞增一位: ①如果前一個員工的InCome的薪酬水平和當前查詢的員工的InCome薪酬水平是相同的,那么@prev<>(@prev:=InCome)會返回FALSE,即0,那么當前員工的排位就會與前一個員工排位一樣; ②如果前一個員工的薪酬水平(InCome)和后一個員工的薪酬水平(InCome)不相同,那么@prev<>(@prev:=InCome)會返回TRUE,即1,那么當前員工的排位就會比前一個員工的排位多1; Mysql排序 在圖中可以看出,第一名有兩位,第二、三…名繼續往后排

(3)薪酬水平相同時,排位相同且占位排序

也存在某些情況,值相同時,排位相同,但接下來的排位按照正常排序排列,就拿數組(56,56,67,67,67,78,79,80)來說,可以形成占位排序:(1,1,3,3,3,6,7,8);此時需要根據上一題作出一些調整,多生成一個變量

SELECT InCome, Rank FROM(SELECT InCome, @rowNum := @rowNum + 1, CASE WHEN @prev = InCome THEN @rank := @rank WHEN @prev <> (@prev := InCome) THEN @rank := @rowNum END AS RankFROM Salary, (SELECT @rowNum := 0, @prev := (SELECT InCome FROM Salary ORDER BY InCome DESC LIMIT 0,1), @rank := 1) initORDER BY InCome DESC)T

這里存在三個變量,前兩個變量與第二題一樣,@rowNum是用作作為遞增列,@prev是用作對比前后值是否一致,而增加@rank變量的具體思路是: ①如果前一名員工與當前員工的薪酬水平不一致,@rank會與@rowNum的值一致,一直遞增,返回給Rank ②如果前一名員工與當前員工的薪酬水平一致,@rank會返回當前@rank的值,無論有多少個員工的薪酬水平一致,都會返回相同的@rank值給Rank 因此可以寫出這樣一個條件語句:

CASE WHEN @prev = InCome THEN @rank := @rank WHEN @prev <> (@prev := InCome) THEN @rank := @rowNum END AS Rank

而同時需要注意的是@prev的初始值應該是按照薪酬水平降序排列的第一條記錄值:

@prev := ( SELECT InCome FROM Salary ORDER BY InCome DESC LIMIT 0,1)

Mysql占位排序

2.查詢每一個部門排名前三的工作年限(組內排名)

SELECT DepartmentName, Name, WorkYearFROM Employees LEFT JOIN departments USING(DepartmentID)WHERE( SELECT COUNT(DISTINCT(E.WorkYear)) FROM Employees AS E WHERE E.DepartmentID = Employees.DepartmentID AND Employees.WorkYear < E.WorkYear) < 2 ORDER BY DepartmentID, WorkYear

這個是稍微復雜一點的嵌套查詢,由于Mysql的GROUP BY函數只能返回1行,所以需要用到其他方法去達到組內排名的目的。 首先子查詢如下:

SELECT COUNT(DISTINCT(E.WorkYear)) FROM Employees AS E WHERE E.DepartmentID = Employees.DepartmentID AND Employees.WorkYear < E.WorkYear

這個子查詢是當外層查詢查詢到一個Employees表中的一行數據(假設為A)時,會傳遞當前行的數據到子查詢中,使得子查詢遍歷部門號與當前數據部門號(A.DepartmentID)相同的數據,查詢到遍歷表中每一行數據與當前數據的工作年齡(A.WorkYear)相比更大的行有多少條 以圖表的形式解釋: Mysql排序 ①假設當前外層查詢到第一行(1,“張揚“, 2),那么會傳遞到子查詢中,與部門編號都為1的員工比較工齡,可以看出有4位員工的工齡是比張揚要大的。 ②假設當前外層查詢到第四行(1,“李麗”,6),那么會傳遞到子查詢中,與部門編號都為1的員工比較工齡,可以看出沒有員工(0<2)的工齡比李麗要大的,那么李麗的這條數據符合條件,會輸出到外層的查詢中;

外層

SELECT DepartmentName, Name, WorkYearFROM Employees LEFT JOIN departments USING(DepartmentID)WHERE(#子查詢) < 2 ORDER BY DepartmentID, WorkYear

此層子查詢用于判斷數據的條數是否符合條件,接上文中子查詢: ①當由于第一行(1,“張揚“, 2)最終輸出4,4>2,那么張揚這條數據就不符合條件,不會輸出; ②當由于第四行(1,“李麗”,6)最終輸出0,0<2,那么李麗的這條數據符合條件,會輸出結果;

Mysql排序

3.查詢每一個部門的排名前三的工薪水平(不同員工同一薪資,只顯示一位)

具體的思路和第2題是一致的,但是由于要連接3個表,看起來有點復雜,但是其實是一樣的做法:

SELECT D.DepartmentName, E.Name, S.InCome FROM Employees EJOIN Salary S USING(EmployeeID)JOIN Departments D USING(DepartmentID)WHERE( SELECT COUNT(DISTINCT(S2.InCome)) FROM Employees E2 JOIN Salary S2 USING(EmployeeID) WHERE S2.InCome > S.InCome AND E.DepartmentID = E2.DepartmentID) < 3 ORDER BY E.DepartmentID

首先,從子查詢入手:

SELECT COUNT(DISTINCT(S2.InCome)) FROM Employees E2 JOIN Salary S2 USING(EmployeeID) WHERE S2.InCome > S.InCome AND E.DepartmentID = E2.DepartmentID

由于薪資和員工不在同一個表中,所以子查詢中需要用連接來查詢;這個子查詢是當外層查詢查詢到一個Employees表、Salary表的復合表(假設表T)中的一行數據(假設為B)時,會傳遞當前行的數據到子查詢中,使得子查詢遍歷部門號與當前數據部門號(B.DepartmentID)相同的數據,查詢到遍歷表中每一行數據與當前數據的薪酬(B.InCome)相比更大的行有多少條 以圖表的形式解釋: MySQL排序 上圖為DepartmentID=’1’時的表T(Employees和Salary表的復合表) ①假設外層查詢得到第一行數據(“1”,“張揚”,5633.00),那么會傳遞到子查詢中,與部門編號都為1的員工比較薪水,可以看出有2位員工的薪酬是比張揚的薪酬要高的。 ②假設外層查詢到第二行數據(“1”,“伍容華”,2100.80),那么會傳遞到子查詢中,與部門編號都為1的員工比較薪水,可以看出有5位員工的薪酬是比張揚的薪酬要高的。

外層查詢:

SELECT D.DepartmentName, E.Name, S.InCome FROM Employees EJOIN Salary S USING(EmployeeID)JOIN Departments D USING(DepartmentID)WHERE(#子查詢) < 3ORDER BY E.DepartmentID

此層子查詢用于判斷數據的條數是否符合條件,接上文中子查詢: ①當由于第一行(”1”,”張揚”, 2)最終輸出2,2<3,那么張揚這條數據就符合條件,會輸出; ②當由于第二行(”1”,”伍容華”,2100.80)最終輸出5,5>2,那么伍容華的這條數據不符合條件,不會輸出結果;

總結:

1.在Mysql的排序當中,由于沒有類似的函數來計算行序號,總的排位需要用到自增列的方式來排,而且自增列的方式有多種,就拿數組(56,56,67,67,67,78,79,80)來說,可以形成三種排列:

(1)即使值相同,也會不會排在同一位:(1,2,3,4,5,6,7,8,) (2)值相同的在同一位,但不占位:(1,1,2,2,2,3,4,5) (3)值相同的在同一位,單占位:(1,1,3,3,3,6,7,8)

2.在Mysql的排序當中,需要查詢到排名前N位的數據,需要結合嵌套查詢以及COUNT()函數,不能單純使用GROUP BY,因為GROUP BY只能返回一條數據

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 阜平县| 游戏| 河池市| 鄂伦春自治旗| 巨野县| 方正县| 开江县| 鱼台县| 左权县| 锡林郭勒盟| 黄平县| 柳江县| 阿拉尔市| 庐江县| 廊坊市| 吉林市| 宣化县| 内黄县| 两当县| 项城市| 阜平县| 彩票| 北京市| 新田县| 沧源| 安阳市| 井冈山市| 新巴尔虎右旗| 澳门| 林甸县| 福海县| 谢通门县| 抚宁县| 白水县| 湄潭县| 登封市| 连州市| 巴林右旗| 株洲县| 麻江县| 积石山|