使用 group by 并加入 sequelize
Using group by and joins in sequelize
我在 PostgreSQL 数据库中有两个表,contracts 和 payments。一份合同已完成多次付款。
我有以下两个模型:
module.exports = function(sequelize, DataTypes) {
var contracts = sequelize.define('contracts', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true
}
}, {
createdAt: false,
updatedAt: false,
classMethods: {
associate: function(models) {
contracts.hasMany(models.payments, {
foreignKey: 'contract_id'
});
}
}
});
return contracts;
};
module.exports = function(sequelize, DataTypes) {
var payments = sequelize.define('payments', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true
},
contract_id: {
type: DataTypes.INTEGER,
},
payment_amount: DataTypes.INTEGER,
}, {
classMethods: {
associate: function(models) {
payments.belongsTo(models.contracts, {
foreignKey: 'contract_id'
});
}
}
});
return payments;
};
我想对每个合同的所有付款进行求和,并使用了这个函数:
models.contracts.findAll({
attributes: [
'id'
],
include: [
{
model: models.payments,
attributes: [[models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']]
}
],
group: ['contracts.id']
})
但它生成以下查询:
SELECT "contracts"."id", "payments"."id" AS "payments.id", sum("payments"."payment_amount") AS "payments.total_cost"
FROM "contracts" AS "contracts"
LEFT OUTER JOIN "payments" AS "payments" ON "contracts"."id" = "payments"."contract_id" GROUP BY "contracts"."id";
我不要求 select payments.id,因为我必须将其包含在我的聚合或按函数分组中,如我的错误所述:
Possibly unhandled SequelizeDatabaseError: error: column "payments.id"
must appear in the GROUP BY clause or be used in an aggregate function
我是不是漏掉了什么?我正在关注 this answer,但即使在那里我也不明白 SQL 请求如何有效。
您可能希望从 payments
中选择问题并加入 contracts
而不是相反?
你能把你的函数写成
models.contracts.findAll({
attributes: [
'models.contracts.id'
],
include: [
{
model: models.payments,
attributes: [[models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']]
}
],
group: ['contracts.id']
})
尝试
group: ['contracts.id', 'payments.id']
此问题已在 Sequelize 3.0.1 上修复,包含模型的主键必须用
排除
attributes: []
并且聚合必须在主模型上完成(this github issue 中的信息)。
因此对于我的用例,代码如下
models.contracts.findAll({
attributes: ['id', [models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']],
include: [
{
model: models.payments,
attributes: []
}
],
group: ['contracts.id']
})
我在 PostgreSQL 数据库中有两个表,contracts 和 payments。一份合同已完成多次付款。
我有以下两个模型:
module.exports = function(sequelize, DataTypes) {
var contracts = sequelize.define('contracts', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true
}
}, {
createdAt: false,
updatedAt: false,
classMethods: {
associate: function(models) {
contracts.hasMany(models.payments, {
foreignKey: 'contract_id'
});
}
}
});
return contracts;
};
module.exports = function(sequelize, DataTypes) {
var payments = sequelize.define('payments', {
id: {
type: DataTypes.INTEGER,
autoIncrement: true
},
contract_id: {
type: DataTypes.INTEGER,
},
payment_amount: DataTypes.INTEGER,
}, {
classMethods: {
associate: function(models) {
payments.belongsTo(models.contracts, {
foreignKey: 'contract_id'
});
}
}
});
return payments;
};
我想对每个合同的所有付款进行求和,并使用了这个函数:
models.contracts.findAll({
attributes: [
'id'
],
include: [
{
model: models.payments,
attributes: [[models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']]
}
],
group: ['contracts.id']
})
但它生成以下查询:
SELECT "contracts"."id", "payments"."id" AS "payments.id", sum("payments"."payment_amount") AS "payments.total_cost"
FROM "contracts" AS "contracts"
LEFT OUTER JOIN "payments" AS "payments" ON "contracts"."id" = "payments"."contract_id" GROUP BY "contracts"."id";
我不要求 select payments.id,因为我必须将其包含在我的聚合或按函数分组中,如我的错误所述:
Possibly unhandled SequelizeDatabaseError: error: column "payments.id" must appear in the GROUP BY clause or be used in an aggregate function
我是不是漏掉了什么?我正在关注 this answer,但即使在那里我也不明白 SQL 请求如何有效。
您可能希望从 payments
中选择问题并加入 contracts
而不是相反?
你能把你的函数写成
models.contracts.findAll({
attributes: [
'models.contracts.id'
],
include: [
{
model: models.payments,
attributes: [[models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']]
}
],
group: ['contracts.id']
})
尝试
group: ['contracts.id', 'payments.id']
此问题已在 Sequelize 3.0.1 上修复,包含模型的主键必须用
排除attributes: []
并且聚合必须在主模型上完成(this github issue 中的信息)。
因此对于我的用例,代码如下
models.contracts.findAll({
attributes: ['id', [models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']],
include: [
{
model: models.payments,
attributes: []
}
],
group: ['contracts.id']
})