如何在HAVING子句中结合MAX函数使用两个列进行筛选?
问题解答
首先明确:MAX是单参数聚合函数,不能直接传入两个参数,但无需创建变量,通过以下几种方法即可实现按date_id和period_time的最大值组合筛选数据,尤其适合百万级大表的场景:
方案1:基于EXISTS子句扩展(兼容原有写法)
在HAVING子句中同时匹配每个PlotsID的最大date_id,以及该date_id下的最大period_time:
SELECT PlotsID, date_id, period_time, fieldID, FieldName FROM data_base db WHERE EXISTS ( SELECT 1 FROM data_base t2 WHERE t2.PlotsID = db.PlotsID GROUP BY t2.PlotsID HAVING db.date_id = MAX(t2.date_id) AND db.period_time = MAX(CASE WHEN t2.date_id = MAX(t2.date_id) THEN t2.period_time END) )
方案2:先聚合再关联(逻辑更清晰)
先通过子查询获取每个PlotsID对应的最大date_id和该日期下的最大period_time,再关联主表筛选:
-- 兼容PostgreSQL的写法(支持FILTER) WITH latest_info AS ( SELECT PlotsID, MAX(date_id) AS max_date_id, MAX(period_time) FILTER (WHERE date_id = MAX(date_id)) AS max_period_time FROM data_base GROUP BY PlotsID ) SELECT db.PlotsID, db.date_id, db.period_time, db.fieldID, db.FieldName FROM data_base db JOIN latest_info li ON db.PlotsID = li.PlotsID AND db.date_id = li.max_date_id AND db.period_time = li.max_period_time
如果是MySQL等不支持FILTER的数据库,可替换为:
WITH latest_info AS ( SELECT PlotsID, MAX(date_id) AS max_date_id, MAX(CASE WHEN date_id = (SELECT MAX(date_id) FROM data_base WHERE PlotsID = t.PlotsID) THEN period_time END) AS max_period_time FROM data_base t GROUP BY PlotsID ) SELECT db.PlotsID, db.date_id, db.period_time, db.fieldID, db.FieldName FROM data_base db JOIN latest_info li ON db.PlotsID = li.PlotsID AND db.date_id = li.max_date_id AND db.period_time = li.max_period_time
方案3:窗口函数(百万级大表最优选择)
使用ROW_NUMBER()窗口函数,仅扫描一次表即可完成筛选,性能远高于前两种方案,适合大数据量场景:
SELECT PlotsID, date_id, period_time, fieldID, FieldName FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY PlotsID ORDER BY date_id DESC, period_time DESC) AS rn FROM data_base ) t WHERE rn = 1
该逻辑为:给每个PlotsID分组内的行按date_id降序、period_time降序排序,标记每行的序号,取序号为1的行,即为每个PlotsID对应最新date_id和该日期下最大period_time的记录。
内容的提问来源于stack exchange,提问作者Dmytro1988
相关产品推荐
相关产品推荐

