Sequelize非原生查询实现:如何统计子查询结果
用Sequelize实现目标查询的两种方案
方案一:简化写法(和原SQL逻辑等价)
你的SQL本质是统计至少有一个地址的客户总数,用INNER JOIN加distinct参数就能直接实现,代码更简洁:
const { Op } = require('sequelize'); const Client = require('../models/Client'); // 替换成你的Client模型路径 const ClientAddress = require('../models/ClientAddress'); // 替换成你的ClientAddress模型路径 const clientCount = await Client.count({ include: [{ model: ClientAddress, required: true, // 用INNER JOIN自动过滤无地址的客户 attributes: [] // 不需要返回地址表字段 }], distinct: true, // 保证每个客户只被统计一次 attributes: ['id'] // 基于客户ID去重统计 });
方案二:严格匹配原嵌套查询结构
如果需要完全复刻原SQL的嵌套子查询写法,可以用Sequelize的子查询功能实现:
const { Op, fn, col, where } = require('sequelize'); const Client = require('../models/Client'); const ClientAddress = require('../models/ClientAddress'); // 构建子查询:获取所有有地址的客户ID const subQuery = Client.findAll({ attributes: ['id'], include: [{ model: ClientAddress, attributes: [], required: false // 对应原SQL的LEFT OUTER JOIN }], group: ['clients.id'], having: where(fn('COUNT', col('client_addresses.id')), '>', 0), raw: true }); // 外层查询:统计子查询结果的数量 const clientCount = await Client.count({ where: { id: { [Op.in]: subQuery } } });
注意事项
- 要先正确定义模型关联:
Client.hasMany(ClientAddress, { foreignKey: 'client_id' }) fn用来调用SQL聚合函数,col指定表字段,避免字段名冲突required: false对应原SQL的LEFT OUTER JOIN,required: true则是INNER JOIN
内容的提问来源于stack exchange,提问作者Erick Avalos
相关产品推荐
相关产品推荐

