SQL Server:多关联表下Incident唯一记录及首个呼叫原因查询
解决方案:获取每个事件的首个呼叫原因
要实现每个事件仅显示首个呼叫原因,核心思路是给每个事件关联的呼叫记录按顺序编号,再筛选出编号为1的记录。以下是几种可行的实现方式:
方法1:使用ROW_NUMBER()窗口函数(通用写法)
这是适配大多数现代数据库(SQL Server、MySQL 8+、PostgreSQL等)的通用方案,需要先明确“首个”的排序依据(比如呼叫时间CreateTime,若无则用PhoneCallEvent的自增ID或创建顺序字段):
SELECT inc.uid, er.Name FROM ( SELECT inc.uid, er.Name, -- 按事件分组,给每个事件的呼叫记录按时间排序编号 ROW_NUMBER() OVER (PARTITION BY inc.GID ORDER BY pce.CreateTime ASC) AS rn FROM [Incident] inc INNER JOIN [PhoneCallEvent] pce ON pce.IncidentRefs = inc.GID INNER JOIN [EventReason] er ON er.GID = pce.eventReasonGID ) AS temp WHERE rn = 1; -- 只保留每个事件的第一条记录
说明:
PARTITION BY inc.GID:按事件ID分组,确保每个事件的呼叫记录单独编号ORDER BY pce.CreateTime ASC:指定排序规则,ASC表示取最早的呼叫记录,若要最新的则改为DESC- 外层查询筛选
rn=1,得到每个事件的首个呼叫原因
方法2:使用CROSS APPLY(SQL Server专属)
如果使用SQL Server,可通过CROSS APPLY直接关联每个事件的第一条呼叫记录,写法更简洁:
SELECT inc.uid, er.Name FROM [Incident] inc CROSS APPLY ( -- 取当前事件的第一条呼叫记录(按时间排序) SELECT TOP 1 pce.eventReasonGID FROM [PhoneCallEvent] pce WHERE pce.IncidentRefs = inc.GID ORDER BY pce.CreateTime ASC ) AS first_pce INNER JOIN [EventReason] er ON er.GID = first_pce.eventReasonGID;
方法3:使用关联子查询(兼容低版本数据库)
如果数据库不支持窗口函数(比如MySQL 5.x),可以用关联子查询筛选每个事件的第一条呼叫记录:
SELECT inc.uid, er.Name FROM [Incident] inc INNER JOIN [PhoneCallEvent] pce ON pce.IncidentRefs = inc.GID INNER JOIN [EventReason] er ON er.GID = pce.eventReasonGID WHERE pce.GID = ( SELECT MIN(pce2.GID) -- 假设GID是自增字段,MIN对应最早的记录 FROM [PhoneCallEvent] pce2 WHERE pce2.IncidentRefs = inc.GID );
注意:
若表中有专门的时间字段,建议用时间字段的最小值匹配,结果更准确:
WHERE pce.CreateTime = ( SELECT MIN(pce2.CreateTime) FROM [PhoneCallEvent] pce2 WHERE pce2.IncidentRefs = inc.GID );
内容的提问来源于stack exchange,提问作者Adrian Cerdas Mora
相关产品推荐
相关产品推荐

