执行下述SQL语句时出现‘未实现匿名复合类型的输入’错误的原因咨询
这个错误在PostgreSQL里一般和类型解析或者复合类型的不当处理有关,咱们结合你的SQL来一步步找问题:
可能的错误原因
字段类型不匹配引发的隐式转换问题
如果table1里的rake或fees字段不是常规数值类型(比如是自定义的复合类型),那SUM()操作返回的结果会是匿名复合类型。之后你用COALESCE把它和数值0混合计算时,PostgreSQL没法处理这种跨类型的操作,就会抛出这个错误。JOIN时的类型推断混乱
要是rakesCTE里的site_id和feesCTE里的site_id类型不一致(比如一个是varchar,一个是text,或者其他不兼容类型),PostgreSQL在做JOIN匹配时可能会错误地尝试将它们转换为复合类型,从而触发错误。多余的
COALESCE干扰类型解析
你用的是INNER JOIN,这意味着r.site_id和f.site_id必然都不为NULL,所以WHERE子句里的COALESCE(r.site_id, f.site_id)完全是多余的。这个不必要的写法可能让PostgreSQL的类型解析器混乱,误判为需要处理复合类型。
解决步骤
检查字段类型
先确认table1.rake和table1.fees的类型是数值型(比如int、numeric、float)。如果是复合类型,你需要先提取复合类型里的数值部分再做求和,比如假设rake是包含amount字段的复合类型,就改成SUM(tbl.rake.amount)。验证
site_id类型一致性
可以临时在SELECT里加上类型检查语句,确认两个CTE的site_id类型是否一致:SELECT (COALESCE(r.rake,0) + COALESCE(f.fees,0))::numeric(18,2) AS calc, pg_typeof(r.site_id) AS r_site_type, pg_typeof(f.site_id) AS f_site_type FROM rakes AS r JOIN fees AS f ON r.site_id=f.site_id WHERE r.site_id IN ('domain.gr', 'domain.uk','domain.com')如果类型不一致,你可以用
::显式转换为同一类型,比如usr.site_id::varchar。简化WHERE子句
把多余的COALESCE去掉,直接用r.site_id IN (...)或者f.site_id IN (...)就可以了。
修改后的SQL示例
另外注意user是PostgreSQL的保留字,最好用双引号括起来避免语法问题:
WITH rakes AS ( SELECT SUM(tbl.rake) AS rake, usr.site_id FROM table1 as tbl INNER JOIN "user" as usr ON usr.id= tbl.user_id WHERE usr.origin <> 'test' AND tbl.created_at>= '2021-01-01' AND tbl.created_at< '2021-07-25' GROUP BY usr.site_id ), fees AS ( SELECT SUM(fees) AS fees, site_id FROM table1 WHERE csv_date>= '2021-01-01' AND csv_date< '2021-07-25' GROUP BY site_id ) SELECT (COALESCE(r.rake,0) + COALESCE(f.fees,0))::numeric(18,2) AS calc FROM rakes AS r JOIN fees AS f ON r.site_id=f.site_id WHERE r.site_id IN ('domain.gr', 'domain.uk','domain.com')
内容的提问来源于stack exchange,提问作者Ann

