如何在不显示ID的前提下筛选邮局工时表中MAX(ID)的唯一记录?
解决重复工时记录保留最大ID的问题
你的思路方向是对的,但HAVING MAX(tt.ID)的写法确实有问题——HAVING必须配合GROUP BY使用,而且需要明确的筛选条件,它是用来过滤聚合后的分组结果,而不是用来筛选单条记录的。针对你的需求,用**窗口函数ROW_NUMBER()**是更合适的方案,它能精准帮你保留每组重复记录中ID最大的那一条,同时满足不显示ID的要求。
修正后的SQL脚本
SELECT h.POSTINDEX, h.LONGNAME_UA, h.SHORTNAME_UA, pt.LONGNAME_UA, h.parent_Id, WORKCOMMENT, INTERVALTYPE, TO_CHAR(TFROM, 'HH24:MI') AS TFROM, TO_CHAR(TTO, 'HH24:MI') AS TTO, WD.NAME_UA, WD.NAME_EN, WD.NAME_RU, WD.SHORTNAME_UA, pt.isVPZ, lr.NAME_UA, lr.CODE FROM ( SELECT tt.*, -- 按重复字段分组,每组内按ID降序排,行号为1的就是ID最大的记录 ROW_NUMBER() OVER ( PARTITION BY tt.POSTOFFICE_ID, tt.dayofweek, tt.TFROM, tt.TTO ORDER BY tt.ID DESC ) AS rn FROM ADDR_PO_WORKSCHEDULE tt WHERE tt.datestop = TO_DATE('9999-12-31','YYYY-MM-DD') AND tt.postoffice_id = 8221 ) AS filtered_tt LEFT JOIN ADDR_POSTOFFICE h ON filtered_tt.POSTOFFICE_ID = h.ID INNER JOIN mdm_lockReason lr ON lr.id = H.LOCK_REASON INNER JOIN ADDR_POSTOFFICEtype pt ON pt.ID = H.POSTOFFICETYPE_ID INNER JOIN ADDR_PO_WORKDAYS wd ON wd.ID = filtered_tt.dayofweek WHERE filtered_tt.rn = 1 -- 只保留每组中ID最大的那条 ORDER BY h.postIndex, h.POSTOFFICETYPE_ID, filtered_tt.dayofweek, filtered_tt.intervaltype, filtered_tt.tFrom, filtered_tt.tto;
关键说明
- 窗口函数
ROW_NUMBER():PARTITION BY后面的字段是用来定义“重复组”的依据,这里我选了POSTOFFICE_ID(同一邮局)、dayofweek(同一星期几)、TFROM和TTO(同一工时时间段),如果你的重复判断还涉及其他字段,可以自行添加到PARTITION BY中。ORDER BY tt.ID DESC让每组内ID最大的记录排在第一位,行号标记为1。
- 外层筛选:通过
WHERE filtered_tt.rn = 1只保留每组中ID最大的那条记录。 - 隐藏ID字段:外层查询完全去掉了
h.ID和tt.ID,满足你不显示ID的需求。
为什么原来的HAVING写法不对?
HAVING是配合GROUP BY使用的,它的作用是过滤聚合后的分组结果(比如筛选MAX(ID) > 100这样的分组),但你的需求是保留每组中的某一条具体记录,不是对分组做统计,所以用窗口函数是更精准的解法。
内容的提问来源于stack exchange,提问作者German Varanytsya
相关产品推荐
相关产品推荐

