如何用SQL WHERE/HAVING子句实现基于日期小时的增量加载?
增量加载original.person到test.person_copy的正确实现
先明确你现有写法的几个核心问题:
HAVING子句必须配合GROUP BY使用,你未指定分组逻辑就直接用HAVING,属于语法错误max(org.date, org.hour)是错误用法:MAX函数仅支持单个参数输入,且date(日期类型)与hour(整数类型)数据类型不兼容,无法直接合并取最大值
下面分两种场景给出正确的增量加载方案:
场景1:同时基于date和hour的精确增量(推荐,因为hour字段重要)
这个方案会精准定位目标表中最新的「日期+小时」组合,仅插入比该组合更新的记录:
方案A:用CTE简化重复子查询(通用SQL)
WITH latest_copy AS ( SELECT MAX(date) AS max_date, -- 找到最大日期对应的最大小时 MAX(hour) FILTER (WHERE date = MAX(date)) OVER () AS max_hour FROM test.person_copy ) INSERT INTO test.person_copy SELECT org.* FROM original.person org CROSS JOIN latest_copy lc WHERE org.date > lc.max_date OR (org.date = lc.max_date AND org.hour > lc.max_hour);
方案B:直接子查询(兼容更多数据库)
INSERT INTO test.person_copy SELECT * FROM original.person org WHERE -- 日期晚于目标表的最大日期 org.date > (SELECT MAX(date) FROM test.person_copy) -- 或者日期等于最大日期,但小时更大 OR ( org.date = (SELECT MAX(date) FROM test.person_copy) AND org.hour > (SELECT MAX(hour) FROM test.person_copy WHERE date = (SELECT MAX(date) FROM test.person_copy)) );
场景2:仅基于date字段的增量加载
如果不需要hour级别的精度,只插入目标表中没有的日期对应的所有记录:
INSERT INTO test.person_copy SELECT * FROM original.person org WHERE org.date > (SELECT MAX(date) FROM test.person_copy);
额外优化(部分数据库支持)
如果你的数据库支持行比较(比如PostgreSQL、MySQL 8.0+),可以用更简洁的写法:
INSERT INTO test.person_copy SELECT * FROM original.person org WHERE (org.date, org.hour) > (SELECT (MAX(date), MAX(hour)) FROM test.person_copy);
注意:我用INSERT INTO替代了你原来的SELECT INTO,因为SELECT INTO通常用于创建新表,而增量加载是往已存在的test.person_copy表中追加数据,用INSERT INTO才是正确的写法。
内容的提问来源于stack exchange,提问作者blitz
相关产品推荐
相关产品推荐

