超全MySQL题(104道、含MySQL新特性解法)由浅入深、笔试必备!(第一部分1-13)

1. 组合两个表

需求:编写一个 SQL 查询,对两表进行关联,展示列为:
FirstName, LastName, City, State

展示效果:

FirstNameLastNameCityState
AllenWangNew York CityNew York
Create table If Not Exists 1_Person (PersonId int, FirstName varchar(255), LastName varchar(255));
Create table If Not Exists 1_Address (AddressId int, PersonId int, City varchar(255), State varchar(255));
Truncate table 1_Person;
Truncate table 1_Address;
insert into 1_Person (PersonId, LastName, FirstName) values (1, 'Wang', 'Allen');
insert into 1_Address (AddressId, PersonId, City, State) values (1, 1, 'New York City', 'New York');

最终SQL:

select
     p.FirstName,
     p.LastName,
     a.City,
     a.State
from 
     1_Person as p 
left join 
     1_Address as a 
on 
     p.PersonId = a.PersonId;

2. 第二高的薪水

需求一:编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary)。如果不存在第二高的薪水,那么查询应返回 null。

展示效果:

SecondHighestSalary
200

建表语句:

Create table If Not Exists 2_Employee (Id int, Salary int);
Truncate table 2_Employee;
insert into 2_Employee (Id, Salary) values (1, 100);
insert into 2_Employee (Id, Salary) values (2, 200);
insert into 2_Employee (Id, Salary) values (3, 300);

最终SQL:

-- 方法一:
select 
 IFNULL((select 
               DISTINCT Salary
	     from  
               2_Employee
	     order by
               Salary DESC
	     limit 1,1
         ), NULL)  as SecondHighestSalary;
    
-- 方法二:
select 
       max(Salary) as SecondHighestSalary 
from 
       2_Employee
where 
       Salary < (select
                       max(Salary) 
                 from 
                       2_Employee
                );
        

提示:LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数。参数必须是一个整数常量。如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。

需求二:编写一个 SQL 查询,获取 Employee 表中第 n 高的薪水(Salary)。

-- 方法一:
CREATE FUNCTION getNthHighestSalary_1(N INT) RETURNS INT
BEGIN
  SET n = N-1;
  RETURN (     
  SELECT DISTINCT Salary FROM 2_Employee ORDER BY Salary DESC LIMIT n,1
  );
END;

select getNthHighestSalary_1(2) ;

-- 方案二:
CREATE FUNCTION getNthHighestSalary_2(N INT) RETURNS INT
BEGIN
  RETURN (     
        SELECT  IF(count<N,NULL,min) 
        FROM
          (SELECT 
                 MIN(Salary) AS min, COUNT(1) AS count
           FROM
                (SELECT 
                       DISTINCT Salary
                 FROM 
                       2_Employee
                 ORDER BY
                       Salary DESC 
                 LIMIT N) AS a
          ) as b
        );
END;

select getNthHighestSalary_2(2) ;

3. 分数排名

需求:编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。

展示效果:

ScoreRank
4.001
4.001
3.852
3.653
3.653
3.504
Create table If Not Exists 3_Scores (Id int, Score DECIMAL(3,2));
Truncate table 3_Scores;
insert into 3_Scores (Id, Score) values (1, 3.5);
insert into 3_Scores (Id, Score) values (2, 3.65);
insert into 3_Scores (Id, Score) values (3, 4.0);
insert into 3_Scores (Id, Score) values (4, 3.85);
insert into 3_Scores (Id, Score) values (5, 4.0);
insert into 3_Scores (Id, Score) values (6, 3.65);

最终SQL:

-- 方法一:
select 
      a.Score as score , 
      (select 
              count(distinct b.Score) 
       from 
              3_Scores b 
       where 
              b.Score >=a.Score) as `rank`
from 
     3_Scores a 
order by 
     Score DESC;
     
-- 方法二:
select 
		Score,
		dense_rank() over(order by Score desc) `rank`
from
		3_Scores;

4. 连续出现的数字

需求:编写一个 SQL 查询,查找所有至少连续出现三次的数字。

展示效果:

ConsecutiveNums
1
Create table If Not Exists 4_Logs (Id int, Num int);
Truncate table 4_Logs;
insert into 4_Logs (Id, Num) values (1, 1);
insert into 4_Logs (Id, Num) values (2, 1);
insert into 4_Logs (Id, Num) values (3, 1);
insert into 4_Logs (Id, Num) values (4, 2);
insert into 4_Logs (Id, Num) values (5, 1);
insert into 4_Logs (Id, Num) values (6, 2);
insert into 4_Logs (Id, Num) values (7, 2);

最终SQL:

-- 方法一:
SELECT
	l1.Num
FROM
    4_Logs l1,
    4_Logs l2,
    4_Logs l3
WHERE
    l1.Id = l2.Id - 1 AND l1.Num = l2.Num
    AND l2.Id = l3.Id - 1 AND l2.Num = l3.Num;
    
-- 方法二:
SELECT 
	l1.Num
FROM
	4_Logs l1
left join
	4_Logs l2
on
	l1.Id = l2.Id - 1
left join
	4_Logs l3
on
	l2.Id = l3.Id - 1
where
	l1.num = l2.num and l2.num = l3.num;
    
-- 方法三:
select distinct Num ConsecutiveNums
from 
	(select
			Num,
			lead(Num,1,null) over(order by id) n2,
			lead(Num,2,null) over(order by id) n3
	from 4_Logs
	)t1
where Num = n2 and Num = n3;

5. 超过经理收入的员工

需求:Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。

数据样式:

IdNameSalaryManagerId
1Joe700003
2Henry800004
3Sam60000null
4Max90000null

展示效果:

Employee
Joe
create table If Not Exists 5_Employee (Id int, Name varchar(255), Salary int, ManagerId int);
truncate table 5_Employee;
insert into 5_Employee (Id, Name, Salary, ManagerId) values (1, 'Joe', 70000, 3);
insert into 5_Employee (Id, Name, Salary, ManagerId) values (2, 'Henry', 80000, 4);
insert into 5_Employee (Id, Name, Salary, ManagerId) values (3, 'Sam', 60000, null);
insert into 5_Employee (Id, Name, Salary, ManagerId) values (4, 'Max', 90000, null);

最终SQL:

SELECT
     a.NAME AS Employee
FROM 
     5_Employee AS a 
JOIN 
     5_Employee AS b
ON 
     a.ManagerId = b.Id 
AND 
     a.Salary > b.Salary;

6. 查找重复的邮箱

需求:编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。

展示效果:

Email
a@b.com
Create table If Not Exists 6_Person (Id int, Email varchar(255));
Truncate table 6_Person;
insert into 6_Person (Id, Email) values (1, 'a@b.com');
insert into 6_Person (Id, Email) values (2, 'c@d.com');
insert into 6_Person (Id, Email) values (3, 'a@b.com');

最终SQL:

select
      Email
from 
      6_Person
group by 
      Email
having 
      count(Email) > 1;

7. 从不订购的客户

需求:某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。

展示效果:

Customers
Henry
Max
Create table If Not Exists 7_Customers (Id int, Name varchar(255));
Create table If Not Exists 7_Orders (Id int, CustomerId int);
Truncate table 7_Customers;
insert into 7_Customers (Id, Name) values (1, 'Joe');
insert into 7_Customers (Id, Name) values (2, 'Henry');
insert into 7_Customers (Id, Name) values (3, 'Sam');
insert into 7_Customers (Id, Name) values (4, 'Max');
Truncate table 7_Orders;
insert into 7_Orders (Id, CustomerId) values (1, 3);
insert into 7_Orders (Id, CustomerId) values (2, 1);

最终SQL:

-- 方法一:
select 
     c.name as 'Customers'
from 
     7_Customers as c
where 
     c.id not in(
        select
              customerid 
        from 
              7_Orders
     );
     
-- 方法二:
select  
	c.Name Customers
from 
	7_Customers  c 
left join 
	7_Orders  o
on 
	c.id = o.CustomerId
where 
	o.id is null;

8. 部门工资最高的员工

需求一:编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。

展示效果:

DepartmentEmployeeSalary
ITJim90000
ITMax90000
SalesHenry80000
Create table If Not Exists 8_Employee (Id int, Name varchar(255), Salary int, DepartmentId int);
Create table If Not Exists 8_Department (Id int, Name varchar(255));
Truncate table 8_Employee;
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (1, 'Joe', 75000, 1);
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (2, 'Jim', 90000, 1);
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (3, 'Henry', 80000, 2);
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (4, 'Sam', 60000, 2);
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (5, 'Max', 90000, 1);
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (6, 'Randy', 85000, 1);
insert into 8_Employee (Id, Name, Salary, DepartmentId) values (7, 'Will', 70000, 1);
Truncate table 8_Department;
insert into 8_Department (Id, Name) values (1, 'IT');
insert into 8_Department (Id, Name) values (2, 'Sales');

最终SQL:

-- 方法一:
SELECT
    d.name AS 'Department',
    e.name AS 'Employee',
    Salary
FROM
    8_Employee as e
JOIN
    8_Department as d
ON
	e.DepartmentId = d.Id
WHERE
    (e.DepartmentId , Salary) IN
    (   SELECT
            DepartmentId, MAX(Salary)
        FROM
            8_Employee
        GROUP BY DepartmentId
	);

-- 方法二:
select 
	Department,Employee,Salary
from 
	(select 
     	d.Name Department,
     	e.Name Employee,
     	e.Salary,
		rank() over(partition by d.id order by Salary desc) rk
	from 
     	8_Employee e 
    join 
     	8_Department d
	on e.DepartmentId=d.id
	)tmp
where rk = 1

需求二:编写一个 SQL 查询,找出每个部门获得前三高工资的所有员工。

展示效果:

DepartmentEmployeeSalary
ITMax90000
ITJim90000
ITRandy85000
ITJoe75000
SalesHenry80000
SalesSam60000

最终SQL:

-- 方法一:
SELECT
    d.Name AS 'Department', e1.Name AS 'Employee', e1.Salary
FROM
    8_Employee e1
JOIN
    8_Department d
ON 
    e1.DepartmentId = d.Id
WHERE
    (SELECT
		COUNT(DISTINCT e2.Salary)
    FROM
      	8_Employee e2
    WHERE
    	e1.Salary < e2.Salary
    AND 
     	e1.DepartmentId = e2.DepartmentId) < 3
order by Department, e1.salary desc;
        
-- 方法二:
select 
	Department,
	Employee,
	Salary
from 
	(select 
     	d.Name  Department,
     	e.Name Employee,
     	e.Salary,
		dense_rank() over(partition by d.id order by Salary desc) rk
	from 
     	8_Employee e 
    join 
     	8_Department d
	on 
     	e.DepartmentId=d.id
	)tmp
where rk <=3

9. 删除重复的电子邮箱

需求:编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。

展示效果:

IdEmail
1john@example.com
2bob@example.com
Create table If Not Exists 9_Person (Id int, email varchar(255));
Truncate table 9_Person;
insert into 9_Person (Id, email) values (1, 'john@example.com');
insert into 9_Person (Id, email) values (2, 'bob@example.com');
insert into 9_Person (Id, email) values (3, 'john@example.com');

最终SQL:

DELETE 
      p1 
FROM 
      9_Person p1,
      9_Person p2
WHERE
      p1.Email = p2.Email AND p1.Id > p2.Id;

10. 上升的温度

需求:编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。

Id
2
4
Create table If Not Exists 10_Weather (Id int, RecordDate date, Temperature int);
Truncate table 10_Weather;
insert into 10_Weather (Id, RecordDate, Temperature) values (1, '2015-01-01', 10);
insert into 10_Weather (Id, RecordDate, Temperature) values (2, '2015-01-02', 25);
insert into 10_Weather (Id, RecordDate, Temperature) values (3, '2015-01-03', 20);
insert into 10_Weather (Id, RecordDate, Temperature) values (4, '2015-01-04', 30);

最终SQL:

-- 方法一:
SELECT
    w1.id AS 'Id'
FROM
    10_Weather w1
JOIN
    10_Weather w2 
ON 
    DATEDIFF(w1.RecordDate, w2.RecordDate) = 1
AND w1.Temperature > w2.Temperature;

-- 方法二:
select 
	Id
from 
	(select 
     	Id,
     	RecordDate,
     	Temperature,
		lag(RecordDate,1,9999-99-99) over (order by RecordDate) yd,
		lag(Temperature,1,999) over(order by RecordDate ) yt
	from 
     	10_Weather 
	)tmp
where 
	Temperature > yt and datediff(RecordDate,yd)=1;

11. 行程和用户

需求:写一段 SQL 语句查出 2019年10月1日 至 2019年10月3日 期间非禁止用户的取消率。基于上表,你的 SQL 语句应返回如下结果,取消率(Cancellation Rate)保留两位小数。取消率的计算方式如下:(被司机或乘客取消的非禁止用户生成的订单数量) / (非禁止用户生成的订单总数)

Trips表:所有出租车的行程信息。每段行程有唯一键 Id,Client_Id 和 Driver_Id 是 Users 表中 Users_Id 的外键。Status 是枚举类型,枚举成员为 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。

IdClient_IdDriver_IdCity_IdStatusRequest_at
11101completed2019-10-01
22111cancelled_by_driver2019-10-01
33126completed2019-10-01
44136cancelled_by_client2019-10-01
51101completed2019-10-02
62116completed2019-10-02
73126completed2019-10-02
821212completed2019-10-03
931012completed2019-10-03
1041312cancelled_by_driver2019-10-03

Users 表存所有用户。每个用户有唯一键 Users_Id。Banned 表示这个用户是否被禁止,Role 则是一个表示(‘client’, ‘driver’, ‘partner’)的枚举类型。

Users_IdBannedRole
1Noclient
2Yesclient
3Noclient
4Noclient
10Nodriver
11Nodriver
12Nodriver
13Nodriver

展示效果:

DayCancellation Rate
2019-10-010.33
2019-10-020.00
2019-10-030.50
Create table If Not Exists 11_Trips (Id int, Client_Id int, Driver_Id int, City_Id int, Status ENUM('completed', 'cancelled_by_driver', 'cancelled_by_client'), Request_at varchar(50));
Create table If Not Exists 11_Users (Users_Id int, Banned varchar(50), Role ENUM('client', 'driver', 'partner'));
Truncate table 11_Trips;
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (1, 1, 10, 1, 'completed', '2019-10-01');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (2, 2, 11, 1, 'cancelled_by_driver', '2019-10-01');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (3, 3, 12, 6, 'completed', '2019-10-01');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (4, 4, 13, 6, 'cancelled_by_client', '2019-10-01');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (5, 1, 10, 1, 'completed', '2019-10-02');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (6, 2, 11, 6, 'completed', '2019-10-02');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (7, 3, 12, 6, 'completed', '2019-10-02');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (8, 2, 12, 12, 'completed', '2019-10-03');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (9, 3, 10, 12, 'completed', '2019-10-03');
insert into 11_Trips (Id, Client_Id, Driver_Id, City_Id, Status, Request_at) values (10, 4, 13, 12, 'cancelled_by_driver', '2019-10-03');
Truncate table 11_Users;
insert into 11_Users (Users_Id, Banned, Role) values (1, 'No', 'client');
insert into 11_Users (Users_Id, Banned, Role) values (2, 'Yes', 'client');
insert into 11_Users (Users_Id, Banned, Role) values (3, 'No', 'client');
insert into 11_Users (Users_Id, Banned, Role) values (4, 'No', 'client');
insert into 11_Users (Users_Id, Banned, Role) values (10, 'No', 'driver');
insert into 11_Users (Users_Id, Banned, Role) values (11, 'No', 'driver');
insert into 11_Users (Users_Id, Banned, Role) values (12, 'No', 'driver');
insert into 11_Users (Users_Id, Banned, Role) values (13, 'No', 'driver');

最终SQL:

方法一:
SELECT 
      T.request_at AS `Day`, 
	  ROUND(
            SUM(IF(T.STATUS = 'completed',0,1))/ COUNT(T.STATUS),
            2
            ) AS `Cancellation Rate`
FROM 
      11_Trips AS T
JOIN 
      11_Users AS U1 
ON 
      T.client_id = U1.users_id AND U1.banned ='No'
WHERE 
      T.request_at BETWEEN '2019-10-01' AND '2019-10-03'
GROUP BY 
      T.request_at;

12. 游戏玩法分析

需求一:写一条 SQL 查询语句获取每位玩家 第一次登陆平台的日期。

Activity表:显示了某些游戏的玩家的活动情况。

player_iddevice_idevent_dategames_played
122016-03-015
122016-03-026
232017-06-251
312016-03-010
342018-07-035

展示效果:

player_idfirst_login
12016-03-01
22017-06-25
32016-03-02
Create table If Not Exists 12_Activity (player_id int, device_id int, event_date date, games_played int);
Truncate table 12_Activity;
insert into 12_Activity (player_id, device_id, event_date, games_played) values (1, 2, '2016-03-01', 5);
insert into 12_Activity (player_id, device_id, event_date, games_played) values (1, 2, '2016-03-02', 6);
insert into 12_Activity (player_id, device_id, event_date, games_played) values (2, 3, '2017-06-25', 1);
insert into 12_Activity (player_id, device_id, event_date, games_played) values (3, 1, '2016-03-01', 0);
insert into 12_Activity (player_id, device_id, event_date, games_played) values (3, 4, '2018-07-03', 5);

最终SQL:

select 
      player_id, 
      min(event_date) as first_login 
from 
      12_Activity 
group by 
      player_id;

需求二:描述每一个玩家首次登陆的设备名称

player_iddevice_id
12
23
31

最终SQL:

方法一:
select
     player_id,
     device_id 
from 
     12_Activity
where
     (player_id,event_date) in (select
                                      player_id, 
                                      min(event_date)
                                from
                                      12_Activity 
                                group by 
                                      player_id);
 
方法二:
select 
	  player_id,
	  device_id
from 
	  (select 
         	player_id,
       		event_date,
       		device_id,
			rank() over(partition by player_id order by event_date) rk
	   from 
       		12_Activity
		) tmp
where rk = 1;

需求三:编写一个 SQL 查询,同时报告每组玩家和日期,以及玩家到目前为止玩了多少游戏。也就是说,在此日期之前玩家所玩的游戏总数。详细情况请查看示例。

player_idevent_dategames_played_so_far
12016-03-015
12016-05-0211
22017-06-251
32016-03-020
32018-07-035

提示:提示:对于 ID 为 1 的玩家,2016-05-02 共玩了 5+6=11 个游戏.
对于 ID 为 3 的玩家,2018-07-03 共玩了 0+5=5 个游戏。

最终SQL:

-- 方法一:
SELECT 
      A.player_id,
      A.event_date,
      SUM(B.games_played) AS `games_played_so_far`
FROM 
      12_Activity AS A
left JOIN 
      12_Activity AS B 
ON 
      A.player_id = B.player_id 
      AND A.event_date >= B.event_date
GROUP BY 
      A.player_id,A.event_date;
      
-- 方法二:
select 
	  player_id,
	  event_date ,
	  sum(games_played) over(partition by player_id order by  event_date )games_played_so_far
from 12_Activity;

需求四:编写一个 SQL 查询,报告在首次登录的第二天再次登录的玩家的百分比,四舍五入到小数点后两位。换句话说,您需要计算从首次登录日期开始至少连续两天登录的玩家的数量,然后除以玩家总数。

fraction
0.33

最终SQL:

-- 方法一:
select 
      round(
            sum(case when datediff(a.event_date,b.first_date)=1 then 1 else 0 end)
               /
               (select count(distinct(player_id)) from 12_Activity)
            ,2 ) as fraction
from 
      12_Activity a,
     (select 
             player_id,
             min(event_date) first_date 
      from 
             12_Activity 
      group by 
             player_id
     ) b
where 
      a.player_id=b.player_id;
      
      
-- 方法二:
select 
      round(avg(a.event_date is not null), 2) fraction
from 
     (select
            player_id,
            min(event_date) as first_date
      from 
            12_Activity
      group by 
            player_id) b
left join 
      12_Activity a 
on 
      b.player_id=a.player_id and datediff(a.event_date, b.first_date)=1

需求五:编写一个 SQL 查询,报告每个安装日期、当天安装游戏的玩家数量和第一天的保留时间。

install_dtinstallsDay1_retention
2016-03-0120.50
2017-06-2510.00

提示:玩家 1 和 3 在 2016-03-01 安装了游戏,但只有玩家 1 在 2016-03-02 重新登录,所以 2016-03-01 的第一天保留时间是 1/2=0.50
玩家 2 在 2017-06-25 安装了游戏,但在 2017-06-26 没有重新登录,因此 2017-06-25 的第一天保留为 0/1=0.00

最终SQL:

-- 方法一
SELECT
      A.event_date AS install_dt,
      COUNT(A.player_id) AS installs,
      round(COUNT(C.player_id)/COUNT(A.player_id),2) AS Day1_retention
FROM
      12_Activity AS A
left JOIN
      12_Activity AS B
ON
      A.player_id = B.player_id AND A.event_date > B.event_date
left JOIN
      12_Activity AS C
ON
      A.player_id = C.player_id AND C.event_date = DATE_ADD(A.event_date,INTERVAL 1 DAY)
WHERE
      B.event_date IS NULL
GROUP BY
      A.event_date;

13. 员工薪水中位数

需求:请编写SQL查询来查找每个公司的薪水中位数。挑战点:你是否可以在不使用任何内置的SQL函数的情况下解决此问题。

展示效果:

IdCompanySalary
5A451
6A513
12B234
9B1154
14C2645
Create table If Not Exists 13_Employee (Id int, Company varchar(255), Salary int);
Truncate table 13_Employee;
insert into 13_Employee (Id, Company, Salary) values (1, 'A', 2341);
insert into 13_Employee (Id, Company, Salary) values (2, 'A', 341);
insert into 13_Employee (Id, Company, Salary) values (3, 'A', 15);
insert into 13_Employee (Id, Company, Salary) values (4, 'A', 15314);
insert into 13_Employee (Id, Company, Salary) values (5, 'A', 451);
insert into 13_Employee (Id, Company, Salary) values (6, 'A', 513);
insert into 13_Employee (Id, Company, Salary) values (7, 'B', 15);
insert into 13_Employee (Id, Company, Salary) values (8, 'B', 13);
insert into 13_Employee (Id, Company, Salary) values (9, 'B', 1154);
insert into 13_Employee (Id, Company, Salary) values (10, 'B', 1345);
insert into 13_Employee (Id, Company, Salary) values (11, 'B', 1221);
insert into 13_Employee (Id, Company, Salary) values (12, 'B', 234);
insert into 13_Employee (Id, Company, Salary) values (13, 'C', 2345);
insert into 13_Employee (Id, Company, Salary) values (14, 'C', 2865);
insert into 13_Employee (Id, Company, Salary) values (15, 'C', 2645);
insert into 13_Employee (Id, Company, Salary) values (16, 'C', 2652);
insert into 13_Employee (Id, Company, Salary) values (17, 'C', 65);

最终SQL:

-- 方法一:
select 
     b.id,
     b.company,
     b.salary
from 
    (select
           id,
           company,
           salary,
           case @com when company then @rk:=@rk+1 else @rk:=1 end rk,
           @com:=company
    from 
           13_Employee,
           (select @rk:=0, @com:='') a
    order by
           company,salary
    ) b
left join 
    (select
           company,
           count(1)/2 cnt
     from 
           13_Employee
     group by company
    ) c
on 
     b.company=c.company
where
     b.rk in (cnt+0.5,cnt+1,cnt);
     
-- 方法二:
select 
	 Id,
	 Company,
	 Salary
from 
	(select
           Id,
     	   Company,
     	   Salary,
		   ROW_NUMBER() over(partition by Company order by Salary) rk,
		   count(*) over(partition by Company) cnt
	from 13_Employee
	)t1
where rk IN (FLOOR((cnt + 1)/2), FLOOR((cnt + 2)/2))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值