如何从租车数据库中查询租赁过同款车型的不重复用户?
解决方法:找出租赁过同款(多用户租赁)车型的去重用户
嘿,我来帮你搞定这个查询需求!你想要的是筛选出那些租赁过被多个不同用户租过的车型的用户,并且每个用户对应每个符合条件的车型只显示一次,对吧?
首先咱们明确核心需求:
- 只保留有至少两个不同用户租赁的车型(比如你的例子里只有
kia符合,bmw和hyundai都只有单个用户租赁,所以排除) - 同一用户租赁同一车型的重复记录要去重
方法一:使用子查询筛选符合条件的车型
这是最直观的写法,先找出符合条件的车型,再关联用户数据:
SELECT DISTINCT u.id, u.name, c.model FROM user u JOIN rent r ON u.id = r.userId JOIN car c ON r.rentId = c.rent WHERE c.model IN ( -- 子查询:找出被至少2个不同用户租赁的车型 SELECT model FROM car JOIN rent ON car.rent = rent.rentId GROUP BY model HAVING COUNT(DISTINCT rent.userId) >= 2 ) ORDER BY c.model, u.id;
逻辑拆解:
- 子查询部分:关联
car和rent表,按model分组,用COUNT(DISTINCT rent.userId)统计每个车型被多少不同用户租赁,筛选出用户数≥2的车型(这里就是kia)。 - 主查询部分:关联三个表,只保留车型在子查询结果里的记录,再用
DISTINCT去掉同一用户同一车型的重复条目(比如alex两次租kia的记录会合并成一条)。
方法二:使用窗口函数(更高效的写法)
如果数据量较大,窗口函数的性能会更优,先计算每个车型的用户数,再筛选:
WITH model_user_stats AS ( SELECT c.model, -- 按车型分组,统计不同用户数量 COUNT(DISTINCT r.userId) OVER (PARTITION BY c.model) AS total_users FROM car c JOIN rent r ON c.rent = r.rentId ) SELECT DISTINCT u.id, u.name, c.model FROM user u JOIN rent r ON u.id = r.userId JOIN car c ON r.rentId = c.rent JOIN model_user_stats mus ON c.model = mus.model WHERE mus.total_users >= 2 ORDER BY c.model, u.id;
逻辑拆解:
- CTE临时结果集:用窗口函数
OVER (PARTITION BY c.model)给每个车型计算对应的不同用户总数。 - 关联筛选:把临时结果集和原表关联,只保留用户数≥2的车型数据,同样用
DISTINCT去重。
最终结果
这两个查询都会返回你期望的结果:
+----+---------+---------+ | id | name | model | +----+---------+---------+ | 1 | alex | kia | | 3 | michael | kia | +----+---------+---------+
为什么你的原查询不符合要求?
你原来的查询只是完成了三张表的关联和排序,但没有:
- 筛选出“被多个用户租赁的车型”这个核心条件,所以会包含
bmw、hyundai这些只有单个用户租赁的车型 - 没有去重同一用户同一车型的重复记录,所以alex的两次kia租赁会显示两条
内容的提问来源于stack exchange,提问作者darkboy




