如何减少对同一表的两次JOIN操作?SQL查询优化问询
嘿,这个问题问得很到位!你目前的SQL虽然能得到正确结果,但确实没必要两次连接同一张ranking_history表——我们可以用条件聚合的方式来简化实现,代码更简洁,执行效率也会更高。
先明确下原表的结构与数据,方便大家理解:
原表信息
1. ranking_history表(用户历史排名记录)
| user_id | ranking | time |
|---|---|---|
| 1 | 2 | 2018-05-21 |
| 1 | 5 | 2018-04-28 |
| 2 | 9 | 2018-05-21 |
| 2 | 1 | 2018-04-28 |
2. user表(用户当前排名)
| id | ranking |
|---|---|
| 1 | 7 |
| 2 | 3 |
优化后的SQL实现
我们只需要连接一次ranking_history表,通过CASE WHEN配合聚合函数,把不同时间的排名数据从行转为列:
SELECT u.id, u.ranking, MAX(CASE WHEN rh.time = '2018-05-21' THEN rh.ranking END) AS last_weeks_ranking, MAX(CASE WHEN rh.time = '2018-04-28' THEN rh.ranking END) AS last_months_ranking FROM user u LEFT JOIN ranking_history rh ON u.id = rh.user_id -- 可选:过滤掉不需要的时间数据,减少聚合计算量 WHERE rh.time IN ('2018-05-21', '2018-04-28') GROUP BY u.id, u.ranking;
为什么这个方法更优?
- 减少连接开销:只需要一次表连接,避免了重复连接同一张表带来的冗余操作
- 逻辑更清晰:通过行转列的思路,直接把需要的两个排名字段一次性计算出来
- 兼容性强:这种条件聚合的写法在绝大多数关系型数据库(MySQL、PostgreSQL、SQL Server等)中都支持
执行结果
运行上述SQL后,会得到你想要的目标结果:
| id | ranking | last_weeks_ranking | last_months_ranking |
|---|---|---|---|
| 1 | 7 | 2 | 5 |
| 2 | 3 | 9 | 1 |
内容的提问来源于stack exchange,提问作者Luvias
相关产品推荐
相关产品推荐

