LEFT JOIN查询按单列去重:同ticketId保留首行如何实现?
你当前查询出现重复行的核心原因是:同一个ticket记录在task表中存在多条满足statusTypeIdTaskCompletion为等待任务状态的关联数据,LEFT JOIN操作会按匹配到的行数对左侧表数据进行扩展,因此同一个ticketId会对应多条查询结果。
方案1:支持窗口函数的数据库(MySQL 8.0+、PostgreSQL、SQL Server等)
使用ROW_NUMBER()窗口函数对同一个ticketId的关联task记录排序,仅保留排序后的第一条即可,修改后的SQL如下:
SELECT t.ticketId ,t.userIdOwner , t.ticketCreateDatetime , t.ticketExpectedEndDatetime , t.ticketUpdateDatetime, t.ticketUpdateBy, t.ticketLabel,t.statusTypeIdTicketState,t.statusTypeIdTicketType,t.statusTypeIdTicketModule, c.clientLabel, c.clientLogoOnList ,s.taskLabel , s.statusTypeIdTaskCompletion FROM ticket AS t INNER JOIN client AS c ON c.clientId = t.clientId LEFT JOIN ( SELECT *, ROW_NUMBER() OVER (PARTITION BY ticketId ORDER BY taskId ASC) AS rn -- 按taskId升序取第一条,可根据需求修改排序规则,比如按task创建时间 FROM task WHERE statusTypeIdTaskCompletion = (SELECT statusTypeId FROM statusType WHERE statusTypeCode = 'waitingTask' AND statusTypeTargetTable = 'statusTypeIdTaskCompletion') ) AS s ON s.ticketId = t.ticketId AND s.rn = 1 WHERE 1=1 AND t.ticketDeleteDatetime IS NULL
如果需要调整“第一条”的判定规则,比如取最新创建的task,只需要修改OVER子句里的ORDER BY字段即可。
方案2:不支持窗口函数的数据库(如MySQL 5.x)
可以通过关联子查询匹配单条task记录,示例如下:
SELECT t.ticketId ,t.userIdOwner , t.ticketCreateDatetime , t.ticketExpectedEndDatetime , t.ticketUpdateDatetime, t.ticketUpdateBy, t.ticketLabel,t.statusTypeIdTicketState,t.statusTypeIdTicketType,t.statusTypeIdTicketModule, c.clientLabel, c.clientLogoOnList ,s.taskLabel , s.statusTypeIdTaskCompletion FROM ticket AS t INNER JOIN client AS c ON c.clientId = t.clientId LEFT JOIN task AS s ON s.ticketId = t.ticketId AND s.statusTypeIdTaskCompletion = (SELECT statusTypeId FROM statusType WHERE statusTypeCode = 'waitingTask' AND statusTypeTargetTable = 'statusTypeIdTaskCompletion') AND s.taskId = (SELECT MIN(taskId) FROM task WHERE ticketId = t.ticketId AND statusTypeIdTaskCompletion = s.statusTypeIdTaskCompletion) WHERE 1=1 AND t.ticketDeleteDatetime IS NULL
内容的提问来源于stack exchange,提问作者hamza arhandouri
相关产品推荐
相关产品推荐

