题目描述

(通过次数499 | 提交次数633,通过率78.83%)

表: Genders
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| user_id     | int     |
| gender      | varchar |
+-------------+---------+
user_id 是该表的主键。
gender 的值是 'female', 'male','other' 之一。
该表中的每一行都包含用户的 ID 及其性别。
表格中 'female', 'male','other' 数量相等。

编写一个SQL查询以重新排列 Genders 表,使行按顺序在'female','other'和'male'之间交替。同时每种性别按照user_id 升序进行排序。
按 上述顺序 返回结果表。

查询结果格式如以下示例所示。
示例 1:
输入: 
Genders 表:
+---------+--------+
| user_id | gender |
+---------+--------+
| 4       | male   |
| 7       | female |
| 2       | other  |
| 5       | male   |
| 3       | female |
| 8       | male   |
| 6       | other  |
| 1       | other  |
| 9       | female |
+---------+--------+
输出: 
+---------+--------+
| user_id | gender |
+---------+--------+
| 3       | female |
| 1       | other  |
| 4       | male   |
| 7       | female |
| 2       | other  |
| 5       | male   |
| 9       | female |
| 6       | other  |
| 8       | male   |
+---------+--------+
解释: 
女性:ID 3、7、9。
其他性别:ID 1、2、6。
男性:ID 4、5、8。
我们在 'female', 'other','male' 之间交替排列表。
注意,每种性别都是按 user_id 升序排序的。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/arrange-table-by-gender

//测试数据
Create table If Not Exists Genders (user_id int, gender ENUM('female', 'other', 'male'));

insert into Genders (user_id, gender) values ('4', 'male');
insert into Genders (user_id, gender) values ('7', 'female');
insert into Genders (user_id, gender) values ('2', 'other');
insert into Genders (user_id, gender) values ('5', 'male');
insert into Genders (user_id, gender) values ('3', 'female');
insert into Genders (user_id, gender) values ('8', 'male');
insert into Genders (user_id, gender) values ('6', 'other');
insert into Genders (user_id, gender) values ('1', 'other');
insert into Genders (user_id, gender) values ('9', 'female');

解题思路

Genders表保存了用户的性别。
题目要求:以’female’,’other’和’male’交替返回所有的用户。性别相同的用户,以user_id升序排序返回。
这道题的难点在于:如何使用SQL实现交替返回用户信息。
对于指定的某类性别来说,实际上就是按user_id升序返回。这个比较简单,直接ORDER BY排序返回即可。但如果有多类性别,怎么保证每类性别的第一个用户在前三行展示呢?
我们知道,如果对性别开窗排序的话,每类性别都会有序号为1、2、3。。。的用户。如果我们再以序号排序,是不是就可以保证是三类性别一组这样返回呢?
答案是肯定的!
那么在这一组内,如何保证三类性别的用户按指定的顺序返回呢?
我们可以为每一类性别预定义一个排序的序号,然后在分组内再以这个序号排序返回即可。

参考SQL

未特别说明的情况下,参考SQL为基于MySQL8.0实现。
with
tmp as (
    select 'female' gender,1 rn
    union all
    select 'other' gender,2 rn
    union all
    select 'male' gender,3 rn
)
select
    a.user_id,
    a.gender
from Genders a
inner join tmp b
on a.gender = b.gender
order by row_number() over(partition by a.gender order by a.user_id),
  b.rn;
  
picture loss