我正在练习使用 MySQL 中的
sakila
数据库。有一个表名称 actor
和一列 last_name
。我想列出所有在第一列中不重复且在第二列中重复的last_name。
输入(只是简单的数据,实际数据存在于sakila数据库Mysql上):
insert into sakila.actor (actor_id, first_name, last_name, last_update)
values (1, 'PENELOPE', 'GUINESS', '2006-02-15 04:34:33'),
(2, 'NICK', 'WAHLBERG', '2006-02-15 04:34:33'),
(3, 'ED', 'CHASE', '2006-02-15 04:34:33'),
(4, 'JENNIFER', 'DAVIS', '2006-02-15 04:34:33'),
(5, 'JOHNNY', 'LOLLOBRIGIDA', '2006-02-15 04:34:33'),
(6, 'BETTE', 'NICHOLSON', '2006-02-15 04:34:33'),
(7, 'GRACE', 'MOSTEL', '2006-02-15 04:34:33'),
(8, 'MATTHEW', 'JOHANSSON', '2006-02-15 04:34:33'),
(9, 'JOE', 'SWANK', '2006-02-15 04:34:33'),
(10, 'CHRISTIAN', 'GABLE', '2006-02-15 04:34:33');
预期输出: 结果中,如果某一列的微粒行数多于其余列,则其余列中的数据将为空
不重复 | 重复 |
---|---|
阿斯泰尔 | 阿克罗伊德 |
BACALL | 艾伦 |
贝尔 | 贝利 |
球 | 贝宁 |
巴里摩尔 | 浆果 |
贝辛格 | 博尔格 |
卑尔根 | 布罗迪 |
伯格曼 | 笼子 |
桦木 | |
绽放 |
我有一个具有
row_number()
功能的解决方案。还有其他解决方案可以解决这个问题吗?希望可以有人帮帮我。预先感谢您!
WITH group_last_name AS
(SELECT last_name,
CASE
WHEN count(*) > 1 THEN 'many'
ELSE 'once'
END AS frequency
FROM actor
GROUP BY last_name),
onceTbl AS
(SELECT last_name,
row_number() OVER (PARTITION BY frequency) AS idx
FROM group_last_name
WHERE frequency = 'once'),
manyTbl AS
(SELECT last_name,
row_number() OVER (PARTITION BY frequency) AS idx
FROM group_last_name
WHERE frequency = 'many')
SELECT onceTbl.last_name AS not_repeated,
manyTbl.last_name AS repeated
FROM manyTbl
LEFT OUTER JOIN onceTbl ON onceTbl.idx = manyTbl.idx
UNION
SELECT onceTbl.last_name AS not_repeated,
manyTbl.last_name AS repeated
FROM onceTbl
LEFT OUTER JOIN manyTbl ON onceTbl.idx = manyTbl.idx;
您可以同时分配列号和行号,为了应对空值,选择不同的行号,最后连接不同的行号并使用条件聚合输出来分隔列
with cte as
(
select last_name, count(*) ,
case when count(*) >1 then 2 else 1 end columnno,
row_number() over (order by last_name) rn
from actor a
group by last_name having count(*) = 1
union all
select last_name, count(*) ,
case when count(*) >1 then 2 else 1 end columnno,
row_number() over (order by last_name) rn
from actor a
group by last_name having count(*) > 1
)
,cte1 as
(select distinct rn from cte)
select max(case when columnno = 1 then last_name else null end) onlyone,
max(case when columnno = 2 then last_name else null end) morethanone
from cte1
join cte on cte.rn = cte1.rn
group by cte1.rn
order by cte1.rn
;