Typeorm中使用QueryBuilder实现SUM子查询报错求助
解决TypeORM QueryBuilder子查询语法错误问题
错误原因
你当前的代码中,使用getQuery()获取子查询的SQL字符串后直接传入.from(),TypeORM会自动为这个字符串添加反引号,导致生成的SQL出现语法错误——MySQL要求子查询必须被包裹在括号中,而不是被反引号包裹。
正确解决方案
方案1:使用TypeORM子查询构建器(推荐,类型安全)
利用TypeORM原生支持的子查询构建器,无需手动拼接SQL字符串,TypeORM会自动处理语法:
// 构建子查询:按invoiceId分组,计算每个发票的总金额 const subQuery = this.itemsRepo .createQueryBuilder('items') .select('SUM(items.price)', 'total') .addSelect('items.invoiceId', 'invoiceId') // 外层查询需要用到invoiceId,必须选中 .groupBy('items.invoiceId'); // 外层查询:统计所有发票的总金额之和,以及发票数量 const result = await this.itemsRepo .createQueryBuilder() .select('SUM(ie.total)', 'totalSum') // 对应原SQL的sum(total) .addSelect('COUNT(ie.invoiceId)', 'invoiceCount') // 对应原SQL的count(invoiceId) .from(subQuery, 'ie') .getRawOne(); // 结果为单行数据,使用getRawOne更合适 return result;
方案2:手动处理SQL字符串(适用于特殊场景)
如果必须使用SQL字符串拼接,需要手动为子查询添加括号,避免TypeORM的自动反引号破坏语法:
// 获取子查询的SQL字符串 const subQuerySql = this.itemsRepo .createQueryBuilder('items') .select('SUM(price)', 'total') .addSelect('invoiceId', 'invoiceId') .groupBy('invoiceId') .getQuery(); // 外层查询:手动包裹子查询为括号形式 const result = await this.itemsRepo .createQueryBuilder() .select('SUM(ie.total)', 'totalSum') .addSelect('COUNT(ie.invoiceId)', 'invoiceCount') .from(`(${subQuerySql})`, 'ie') // 关键:用括号包裹子查询SQL .getRawOne(); return result;
验证生成的SQL
两种方案最终都会生成你需要的目标SQL:
SELECT SUM(ie.total) AS `totalSum`, COUNT(ie.invoiceId) AS `invoiceCount` FROM ( SELECT SUM(items.price) AS `total`, items.invoiceId AS `invoiceId` FROM `items` `items` GROUP BY items.invoiceId ) `ie`
内容的提问来源于stack exchange,提问作者junnubhai
相关产品推荐
相关产品推荐

