首页 > 试题广场 >

给出employees表中排名为奇数行的first_name

[编程题]给出employees表中排名为奇数行的first_name
  • 热度指数:207508 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
对于employees表中,输出first_name排名(按first_name升序排序)为奇数的first_name

employees表如下:

emp_no birth_date first_name last_name gender hire_date
10001 1953-09-02 Georgi Facello M 1986-06-26
10002 1964-06-02 Bezalel Simmel F 1985-11-21
10005 1955-01-21 Kyoichi Maliniak M 1989-09-12
10006 1953-04-20 Anneke Preusig F 1989-06-02


输出格式:
first
Georgi
Anneke
请你在不打乱原序列顺序的情况下,输出:按first_name排升序后,取奇数行的first_name
如对以上示例数据的first_name排序后的序列为:Anneke、Bezalel、Georgi、Kyoichi。
排序后的序列中的Georgi排名为3,Anneke排名为1,所以按原序列顺序输出Georgi、Anneke

示例1

输入

drop table if exists  `employees` ; 
CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` char(1) NOT NULL,
  `hire_date` date NOT NULL,
  PRIMARY KEY (`emp_no`));
INSERT INTO employees VALUES(10001,'1953-09-02','Georgi','Facello','M','1986-06-26');
INSERT INTO employees VALUES(10002,'1964-06-02','Bezalel','Simmel','F','1985-11-21');
INSERT INTO employees VALUES(10005,'1955-01-21','Kyoichi','Maliniak','M','1989-09-12');
INSERT INTO employees VALUES(10006,'1953-04-20','Anneke','Preusig','F','1989-06-02');

输出

Georgi
Anneke
select first
from
    (select
        emp_no,
        if(rk%2=1,first_name,null) as first
    from
        (select
            emp_no,
            first_name,
            rank()over(order by first_name) as rk
        from employees)f)f1
where first is not null
order by emp_no
1. f 表利用窗口函数对所有first_name 进行排序
2. f1 表利用if函数选择出奇数排名对应的first,并将非奇数排名对应的first设为NULL
3.select出非null的first
(因为结果是按照emp_no进行排序,所以要一直保留emp_no)
发表于 2025-06-28 11:18:11 回复(0)
如果只用窗口函数无法满足题目要求的按照原表的firs_name顺序输出的要求,因此join原表和窗口函数row_number
发表于 2025-05-25 16:53:29 回复(0)
题目最后一行的说明,所以按原序列顺序输出Georgi、Anneke。
这个按照原顺序麻烦一点。
一种思路是,利用 `emp_no` 列进行排序,名次用窗口函数或者自关联分组计数
-- 使用窗口函数取得排名
select 
first_name
from (
    select 
      first_name
    , row_number() over(order by first_name asc) as rn
    from employees
    order by emp_no asc 
) t
where rn % 2 = 1
;
-- 使用自关联分组计数
select 
first_name
from (
    select 
    e1.emp_no as emp_no 
    , min(e1.first_name) as first_name
    from employees e1
    inner join employees e2
        on e2.first_name<=e1.first_name
    group by e1.emp_no
    having count(1) % 2 = 1
    order by emp_no asc 
) t
;

另一种思路,是使用子查询,如果直接在 where 子句中使用,相比于在 select 中使用子查询再用 where 过滤,更直接一点
select 
  first_name
from employees e1
where (
  select 
  count(1)
  from employees e2
  where e2.first_name<=e1.first_name) % 2 = 1
;
发表于 2025-03-27 17:07:47 回复(0)
with t1 as (select *, dense_rank() over(order by first_name) as rk
from employees)

select first_name
from t1
where MOD(rk,2) <>0
order by emp_no asc

发表于 2025-03-11 17:48:00 回复(0)
两种解法
第一种:取出想要的名字后发现是排序后的结果,所以右连接原表后再输出
select employees.first_name
from (
    select first_name,rank()over(order by first_name) a
    from employees

) as rk join employees on rk.first_name = employees.first_name
where rk.a is not null and (rk.a)%2 = 1


第二种:
select first_name
from employees
where first_name in (
    select first_name 
    from (select first_name, rank()over(order by first_name) a
    from employees ) as rk
    where (rk.a)%2 = 1 
) 



发表于 2025-02-21 16:31:43 回复(0)
WITH tb AS ( SELECT employees.first_name,employees.emp_no, ROW_NUMBER() over ( ORDER BY employees.first_name ) AS row_num 
FROM
  employees)
  select first_name from tb where tb.row_num % 2 =1
  order by tb.emp_no
这应该是最简单的吧
发表于 2025-02-04 19:19:45 回复(0)
select first_name from employees where first_name in (
select
    first_name
from
    (
        select
            *,
            row_number() over (
                order by
                    first_name
            ) as rk
        from
            employees
    ) temp
where rk % 2 = 1
)

发表于 2025-01-07 15:02:17 回复(0)
select first_name
from (select first_name, dense_rank()over(order by first_name asc) rk
from employees
order by emp_no) ranked
where rk % 2 = 1
先增加一列排名,这里用了dense_rank是防止排名相同,然后再用子查询
发表于 2025-01-04 16:21:59 回复(0)
select e1.first_name as first
from employees as e1
inner join
(select ROW_NUMBER () over ( order by first_name asc) as num,first_name
from employees
) as e2 on e1.first_name = e2.first_name
where mod (num,2) = 1

主要是2个函数,ROW_NUMBER () over ( order by first_name asc) as num 加序号,mod (num,2) = 1 余数公式判断是奇数
症结点主要是不影响原有的排序,所以进行了内链接
发表于 2024-12-17 04:10:17 回复(0)
select first_name from employees
where first_name in
(select first_name
from
    (
    select
    first_name,
    rank() over(order by first_name) as t_rank
    from
    employees
    ) t
where mod(t_rank,2) = 1)
发表于 2024-09-12 16:53:56 回复(0)
with t1 as (
    select first_name,row_number() over(order by first_name) as rk from employees
)
select first_name from employees where first_name in(select first_name from t1 where t1.rk%2=1)

发表于 2024-08-16 14:49:46 回复(1)
with a as (select  first_name, row_number() over (order by first_name) as rn from employees) select first_name from a where mod(rn,2) <> 0 order by first_name desc ;
发表于 2024-07-11 16:53:24 回复(0)

用emp_no自连接顺序会变,还是用子查询吧。

select first_name first 
from employees
where emp_no in (
    select
        emp_no
    from (
        select
            emp_no,
            row_number() over (order by first_name) rk
        from employees
    ) t
    where rk%2=1
)
发表于 2024-06-10 18:23:33 回复(0)
无线嵌套
select first_name from employees where emp_no in
(select emp_no from 
(select emp_no,
rank() over(order by first_name asc) as nn
from employees )a
where a.nn % 2 !=0) 

发表于 2024-05-29 10:45:27 回复(0)
select first_name
from employees
where first_name in(
select if(rank()over(order by first_name)%2=1, first_name, null)
from employees )
看了下感觉是最清晰的解法,用 if 函数处理rank即可
发表于 2024-05-10 19:24:30 回复(0)
# 首先按照first_name进行升序排序
with t as(
select first_name,row_number() over(order by first_name) as rk from employees
),

#其次按照排序后的奇数行获取first_name
t1 as(
select first_name from t
where rk % 2 != 0
)

#接着从原表中找到这些满足条件的first_name
select first_name from employees
where first_name in (select first_name from t1)

#Ps,坑在于最后的数据不需要排序,所以得从原表中拿

发表于 2024-05-09 11:04:53 回复(0)
SELECT 
    first_name AS first
FROM (
    SELECT 
        first_name,
        ROW_NUMBER()OVER(ORDER BY first_name) AS row_first_name
    FROM employees
    GROUP BY first_name
) AS order_first_name
JOIN employees e USING(first_name)
WHERE MOD(row_first_name, 2) <> 0;

OR:

SELECT 
    first_name AS first
FROM (
    SELECT 
        first_name,
        ROW_NUMBER()OVER(ORDER BY first_name) AS row_first_name
    FROM employees
    GROUP BY first_name
) AS order_first_name
JOIN employees e USING(first_name)
WHERE row_first_name %2 <> 0;

发表于 2024-04-07 21:14:32 回复(0)
这个题目比较关键的是,只要在 SQL 中使用过 ORDER BY 字段(包括在 开窗函数 OVER 中),都会导致最后返回的结果的顺序发生改变,因此如果想要结果顺序不变,则应该在子查询中按照 emp_no 排序,以此保证依然是原始的顺序
```
SELECT
    first
FROM
    (
        SELECT
            first_name first,
            row_number() OVER (
                ORDER BY
                    first_name
            ) t_rank
        FROM
            employees
        ORDER BY
            emp_no
    ) m
WHERE 
    m.t_rank %2=1

```
编辑于 2024-02-29 11:43:02 回复(0)