基于两列关联表并取另一列最大值的SQL查询需求
问题描述
现有关联HistoricCall表与Responses表的SQL语句如下:
SELECT * FROM HistoricCall h INNER JOIN Responses r ON h.projectid = r.projectId AND h.caseId = r.caseId
其中HistoricCall表包含callNumber字段,用于记录每次呼叫的尝试次数。
现需编写查询语句,实现以下查询逻辑:
SELECT h.callDate, r.cellmap, COUNT(*)
但仅保留**每个projectId+caseId组合对应最大callNumber**的h.callDate数据。
表结构及示例数据
HistoricCall表
| projectId | caseId | callNumber | callDate |
|---|---|---|---|
| 100018 | 0000000001 | 1 | 2014-09-11 16:32:11.000 |
| 100018 | 0000000001 | 2 | 2014-09-11 20:43:01.000 |
| 100018 | 0000000001 | 3 | 2014-09-12 21:09:55.000 |
| 100018 | 0000000001 | 4 | 2014-09-13 14:58:14.000 |
| 100018 | 0000000001 | 5 | 2014-09-14 16:42:27.000 |
| 100018 | 0000000001 | 6 | 2014-09-16 21:54:09.000 |
| 100018 | 0000000001 | 7 | 2014-09-16 22:30:24.000 |
| 100018 | 0000000002 | 1 | 2014-09-11 16:36:17.000 |
| 100018 | 0000000002 | 2 | 2014-09-13 18:05:44.000 |
| 100018 | 0000000002 | 3 | 2014-09-14 16:39:03.000 |
Responses表
| projectId | caseId | cellmap |
|---|---|---|
| 637850 | 0000000001 | 9101 |
| 637850 | 0000000002 | 9052 |
| 637850 | 0000000003 | 5071 |
| 637850 | 0000000004 | 5173 |
| 637850 | 0000000005 | |
| 637850 | 0000000006 | 8062 |
| 637850 | 0000000007 | 0012 |
| 637850 | 0000000008 | 5292 |
| 637850 | 0000000009 | 9230 |
| 637850 | 0000000010 | 5187 |
期望结果
| projectId | callDate | cellmap | Count |
|---|---|---|---|
| 637850 | 2014-09-11 | 0012 | 3 |
| 637850 | 2014-09-11 | 0014 | 7 |
| 637850 | 2014-09-12 | 0012 | 4 |
| 637850 | 2014-09-12 | 0014 | 2 |
解决方案
核心思路是先筛选出每个projectId+caseId组合下最大callNumber对应的记录,再关联Responses表做分组统计,以下是两种常用实现方案:
方案一:子查询筛选最大呼叫次数
SELECT r.projectId, CONVERT(VARCHAR(10), h.callDate, 23) AS callDate, r.cellmap, COUNT(*) AS Count FROM HistoricCall h INNER JOIN ( -- 先获取每个分组的最大callNumber SELECT projectId, caseId, MAX(callNumber) AS maxCallNumber FROM HistoricCall GROUP BY projectId, caseId ) max_h ON h.projectId = max_h.projectId AND h.caseId = max_h.caseId AND h.callNumber = max_h.maxCallNumber INNER JOIN Responses r ON h.projectId = r.projectId AND h.caseId = r.caseId GROUP BY r.projectId, CONVERT(VARCHAR(10), h.callDate, 23), r.cellmap ORDER BY callDate, cellmap;
方案二:窗口函数标记最新呼叫记录
WITH ranked_calls AS ( SELECT *, -- 按分组排序,最大callNumber排第1位 ROW_NUMBER() OVER (PARTITION BY projectId, caseId ORDER BY callNumber DESC) AS rn FROM HistoricCall ) SELECT r.projectId, CONVERT(VARCHAR(10), rc.callDate, 23) AS callDate, r.cellmap, COUNT(*) AS Count FROM ranked_calls rc INNER JOIN Responses r ON rc.projectId = r.projectId AND rc.caseId = r.caseId WHERE rc.rn = 1 -- 仅保留最大callNumber的记录 GROUP BY r.projectId, CONVERT(VARCHAR(10), rc.callDate, 23), r.cellmap ORDER BY callDate, cellmap;
补充说明
- 若使用MySQL数据库,将
CONVERT(VARCHAR(10), callDate, 23)替换为DATE(callDate)即可实现日期格式化。 - 分组统计时按
projectId、格式化后的日期、cellmap聚合,最终结果按日期和cellmap排序,与期望结果格式对齐。
内容的提问来源于stack exchange,提问作者renlaforest
相关产品推荐
相关产品推荐

