MySQL迁移PostgreSQL查询90天未创建职位报日期类型错误
问题根因
你写的SQL存在4个核心问题,是触发报错、逻辑不符合预期的根源:
- 类型不匹配:
jobs.created_at::date >= 90写法中,右值是整数类型90,PostgreSQL是强类型数据库,不存在日期类型与整数类型直接比较的操作符,直接抛出你看到的operator does not exist: date >= integer错误。计算90天前的时间点需要用标准interval时间间隔语法,不能直接写整数和日期比较。 - 子查询结构非法:你写的
IN (SELECT jobs.created_at::date >= 90)子查询没有声明FROM子句,本身就是不完整的查询结构,之前MySQL的写法能跑完全是靠数据库本身的非标准兼容兜底。 - 原MySQL逻辑本身不规范:你之前在BI里跑通的MySQL写法本身属于歪打正着——
jobs.created_at BETWEEN ...返回的是布尔值(0/1),拿整数类型的主键jobs.id去IN布尔值结果集,完全靠MySQL的宽松隐式类型转换才出结果,本身逻辑可读性差、也不符合SQL标准,迁移到强类型的PostgreSQL必然报错。 - 语法笔误+过滤位置错误:
law_firms.name not like '%Temp%\"'末尾多写了一个双引号,会导致字符串匹配规则不符合预期;如果用LEFT JOIN写法,近90天职位的过滤条件写在WHERE子句会把从未发过职位的律所误过滤,这类主体本身也满足「超过90天未创建职位」的要求。
正确可运行的PostgreSQL实现
推荐用NOT EXISTS做反连接查询,语义清晰,PostgreSQL优化器对该写法的执行效率优化更好,也不会出现JOIN过滤位置写错的问题:
SELECT law_firms.name AS "Law Firm" FROM law_firms WHERE law_firms.deleted_at IS NULL AND law_firms.name NOT LIKE '%Temp%' AND law_firms.name NOT LIKE '%Individual%' AND NOT EXISTS ( SELECT 1 FROM jobs WHERE jobs.law_firm_id = law_firms.id -- 如果created_at字段是纯date类型,可把current_timestamp换成current_date AND jobs.created_at >= current_timestamp - INTERVAL '90 days' ) GROUP BY law_firms.name;
如果你习惯用LEFT JOIN写法,注意必须把近90天职位的过滤条件放在ON子句中,不能放到WHERE里:
-- LEFT JOIN 实现版本(不推荐,性能弱于NOT EXISTS写法) SELECT law_firms.name AS "Law Firm" FROM law_firms LEFT JOIN jobs ON jobs.law_firm_id = law_firms.id AND jobs.created_at >= current_timestamp - INTERVAL '90 days' WHERE law_firms.deleted_at IS NULL AND law_firms.name NOT LIKE '%Temp%' AND law_firms.name NOT LIKE '%Individual%' AND jobs.id IS NULL GROUP BY law_firms.name;
迁移注意点
- 时间计算不要用整数直接和日期/时间类型比较,必须通过
INTERVAL 'xx days'声明时间间隔,避免隐式类型转换问题。 - 从MySQL迁移到PostgreSQL时,不要依赖MySQL特有的宽松隐式类型转换逻辑,所有比较、计算的字段类型必须保持一致,子查询要写全完整结构。
内容的提问来源于stack exchange,提问作者gothxbrooks
相关产品推荐
相关产品推荐

