部門内で最も給与の高い従業員(部門内で上位 3 位の給与を持つ従業員)

テーブル構造

 従業員

部門

 

CREATE TABLE `department`  (
  `id` int(0) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO `department` VALUES (1, 'IT 部门');
INSERT INTO `department` VALUES (2, '销售部门');

CREATE TABLE `employee`  (
  `id` int(0) NOT NULL,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `salary` int(0) NULL DEFAULT NULL,
  `departmentId` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO `employee` VALUES (1, 'joe', 70000, 1);
INSERT INTO `employee` VALUES (2, 'jim', 90000, 2);
INSERT INTO `employee` VALUES (3, 'heney', 80000, 2);
INSERT INTO `employee` VALUES (4, 'sam', 70000, 2);
INSERT INTO `employee` VALUES (5, 'kity', 60000, 1);
INSERT INTO `employee` VALUES (6, 'hellen', 68000, 1);
INSERT INTO `employee` VALUES (7, 'hym', 68000, 1);
INSERT INTO `employee` VALUES (8, 'liliy', 72000, 2);

1. 名のみをクエリする場合は、最も単純な方法を使用できます。

各部門の部門IDと1位の給与を問い合わせる

1.查询各个部门第一名的部门Id和薪资
SELECT departmentId,MAX(salary) departmentId FROM employee GROUP BY departmentId;

+--------------+--------------+
| departmentId | departmentId |
+--------------+--------------+
|            1 |        70000 |
|            2 |        90000 |
+--------------+--------------+

2.使用in
SELECT * FROM employee JOIN department on employee.departmentId = department.id 
WHERE #双条件in
  (employee.departmentId,employee.salary) 
in #各部门第一名
	(SELECT departmentId,MAX(salary) departmentId FROM employee GROUP BY departmentId) ;

+----+------+--------+--------------+----+--------------+
| id | name | salary | departmentId | id | name         |
+----+------+--------+--------------+----+--------------+
|  1 | joe  |  70000 |            1 |  1 | IT 部门      |
|  2 | jim  |  90000 |            2 |  2 | 销售部门     |
+----+------+--------+--------------+----+--------------+

2. 上位 3 つをクエリする

1. まず、mysql のランキング関数、rank()、dense_rank()、row_number() の 3 つの関数を導入します。

Rank()   は 1、2、2、4 としてソートされます。(同率2位のうち1名が3位となるため、3位は飛ばします。下図の順位は順位です)

name、詳細はid=6、7、5のランクを参照)

Partition by は、関数ソートの group by と同等です。

SELECT *,rank() over(partition by departmentId ORDER BY salary desc) ranks FROM employee;

+----+--------+--------+--------------+-------+
| id | name   | salary | departmentId | ranks |
+----+--------+--------+--------------+-------+
|  1 | joe    |  70000 |            1 |     1 |
|  6 | hellen |  68000 |            1 |     2 |
|  7 | hym    |  68000 |            1 |     2 |
|  5 | kity   |  60000 |            1 |     4 |
|  2 | jim    |  90000 |            2 |     1 |
|  3 | heney  |  80000 |            2 |     2 |
|  8 | liliy  |  72000 |            2 |     3 |
|  4 | sam    |  70000 |            2 |     4 |
+----+--------+--------+--------------+-------+

row_number()は行番号に従って 1、2、3、4 としてソートされます。

SELECT *,row_number() over(partition by departmentId ORDER BY salary desc) ranks FROM employee;
| id | name   | salary | departmentId | ranks |
+----+--------+--------+--------------+-------+
|  1 | joe    |  70000 |            1 |     1 |
|  6 | hellen |  68000 |            1 |     2 |
|  7 | hym    |  68000 |            1 |     3 |
|  5 | kity   |  60000 |            1 |     4 |
|  2 | jim    |  90000 |            2 |     1 |
|  3 | heney  |  80000 |            2 |     2 |
|  8 | liliy  |  72000 |            2 |     3 |
|  4 | sam    |  70000 |            2 |     4 |

Density_rank()は 1,2,2,3 としてソートされます。(denseは英語で「密な、稠密」を意味します。dense_rank()はソート番号が連続していて途切れないことを意味します)

SELECT *,dense_rank() over(partition by departmentId ORDER BY salary desc) ranks FROM employee;

| id | name   | salary | departmentId | ranks |
+----+--------+--------+--------------+-------+
|  1 | joe    |  70000 |            1 |     1 |
|  6 | hellen |  68000 |            1 |     2 |
|  7 | hym    |  68000 |            1 |     2 |
|  5 | kity   |  60000 |            1 |     3 |
|  2 | jim    |  90000 |            2 |     1 |
|  3 | heney  |  80000 |            2 |     2 |
|  8 | liliy  |  72000 |            2 |     3 |
|  4 | sam    |  70000 |            2 |     4 |
+----+--------+--------+--------------+-------+

2. mysql 関数を使用して上位 3 人の従業員をクエリします。

1.先查询出薪资排名
SELECT *,rank() over(partition by departmentId ORDER BY salary desc) ranks FROM employee;
| id | name   | salary | departmentId | ranks |
+----+--------+--------+--------------+-------+
|  1 | joe    |  70000 |            1 |     1 |
|  6 | hellen |  68000 |            1 |     2 |
|  7 | hym    |  68000 |            1 |     2 |
|  5 | kity   |  60000 |            1 |     4 |
|  2 | jim    |  90000 |            2 |     1 |
|  3 | heney  |  80000 |            2 |     2 |
|  8 | liliy  |  72000 |            2 |     3 |
|  4 | sam    |  70000 |            2 |     4 |

2.再根据已查出的薪资排名,筛选出前三名员工
SELECT * FROM department 
JOIN (
	SELECT *,rank() over(partition by departmentId ORDER BY salary desc) ranks FROM employee) a 
on department.id = a.departmentId WHERE a.ranks <=3 ;

| id | name         | id | name   | salary | departmentId | ranks |
+----+--------------+----+--------+--------+--------------+-------+
|  1 | IT 部门      |  1 | joe    |  70000 |            1 |     1 |
|  1 | IT 部门      |  6 | hellen |  68000 |            1 |     2 |
|  1 | IT 部门      |  7 | hym    |  68000 |            1 |     2 |
|  2 | 销售部门     |  2 | jim    |  90000 |            2 |     1 |
|  2 | 销售部门     |  3 | heney  |  80000 |            2 |     2 |
|  2 | 销售部门     |  8 | liliy  |  72000 |            2 |     3 |

3. 従来の方法を使用して上位 3 つをクエリします 

1.查询出每个薪资数,比其它薪资数高的数量
select * from employee a,employee b where a.departmentId=b.departmentId and a.salary<b.salary;

このステートメントを翻訳すると、次のような意味になります。

70000未満の給与のレコードが3件あります

給与が 68000 未満のレコードが 2 件あります

68000 が 2 つあるのに、なぜ 1 レコードが取得されなかったのか

給与が 60000 未満のレコードは 0 件あります

select * from employee a JOIN  department ON a.departmentId = department.id 
where (
	select count(1) from employee where a.departmentId=departmentId and a.salary<salary) <3 
order by a.departmentId, a.salary desc;


# where中select count(1) from employee where a.departmentId=departmentId and a.salary<salary) <3

整体查询时a.salary<salary 的意思是,employee的薪资比a中的高(注意:和之前的单独查询是意思不一样哦)
那么

当a中是70000是,count出来薪资比它高的数量是0条,小于3条  满足
当a中是68000是,count出来薪资比它高的数量是1条,小于3条  满足
当a中是60000是,count出来薪资比它高的数量是3条,等于3条  不满足


| id | name   | salary | departmentId | id | name         |
+----+--------+--------+--------------+----+--------------+
|  1 | joe    |  70000 |            1 |  1 | IT 部门      |
|  6 | hellen |  68000 |            1 |  1 | IT 部门      |
|  7 | hym    |  68000 |            1 |  1 | IT 部门      |
|  2 | jim    |  90000 |            2 |  2 | 销售部门     |
|  3 | heney  |  80000 |            2 |  2 | 销售部门     |
|  8 | liliy  |  72000 |            2 |  2 | 销售部门     |


 

 

おすすめ

転載: blog.csdn.net/zs319428/article/details/120880337