TypeORM使用QueryBuilder执行group by分组统计时报错如何解决
TypeORM QueryBuilder分组查询报错解决方案
报错根因
- 语法错误:你写的
SUM(balance.amount缺少右括号,导致生成的SQL语句函数未闭合,直接触发PostgreSQL 42601语法错误码 - 逻辑错误:使用
leftJoinAndSelect会自动加载balance、token两个实体的全部字段到SELECT列表,而GROUP BY仅指定了balance.tokenId,不符合SQL分组规范(未聚合的非分组字段不允许出现在SELECT列表中)
修正后代码
import { EntityRepository, Repository } from "typeorm"; import { Address } from "../../../entity"; import { Balance } from "../../../entity/Balance"; @EntityRepository(Balance) export class BalanceRepository extends Repository<Balance> { async findByAddress(address: Address): Promise<{amount: string, token: number|string}[]> { return this.createQueryBuilder("balance") .select("SUM(balance.amount)", "amount") // 如果要返回token symbol就把下面的token.id换成token.symbol .addSelect("token.id", "token") .leftJoin("balance.token", "token") // 新增指定address的过滤条件 .where("balance.addressId = :addressId", { addressId: address.id }) .groupBy("token.id") .getRawMany(); } }
调整说明
- 补全SUM函数的闭合括号,修复基础语法错误
- 替换
leftJoinAndSelect为leftJoin,避免加载不必要的实体字段,适配分组查询要求 - 显式指定需要返回的聚合结果和关联字段,非聚合的token字段同步加入GROUP BY列表,符合SQL标准
- 新增where条件通过外键
addressId过滤指定地址的余额记录,满足你后续的过滤需求 - 输出格式直接匹配你要求的结构,可通过修改
addSelect的字段灵活切换返回tokenId还是token.symbol
注意事项
你定义的amount字段是numeric类型,聚合后返回结果为字符串格式,可避免大数字精度丢失,如果业务要求数字类型可自行转换,大额资产建议优先用字符串存储传输。
内容的提问来源于stack exchange,提问作者user16780074
相关产品推荐
相关产品推荐

