使用group by并加入sequelize

时间:2015-01-29 03:45:09

标签: sql node.js postgresql sequelize.js

我在PostgreSQL数据库上有两个表,合同和付款。一份合同已完成多笔付款。

我有以下两种模式:

 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";

我没有要求选择payments.id,因为我必须按功能将其包含在我的聚合或组中,如我所犯的错误所述:

  

可能未处理的SequelizeDatabaseError:错误:列" payments.id"   必须出现在GROUP BY子句中或用于聚合函数

我在这里遗漏了什么吗?我跟随this answer,但即使在那里,我也不了解SQL请求的有效性。

4 个答案:

答案 0 :(得分:19)

此问题已在Sequelize 3.0.1上修复,必须排除所包含模型的主键

yourJsonObject.forEach(function(obj) {
    console.log(obj.feature_image.ID); // shows 28
});

并且必须在主模型上完成聚合(this github issue中的信息)。

因此,对于我的用例,代码如下

attributes: []

答案 1 :(得分:2)

尝试

group: ['contracts.id', 'payments.id']

答案 2 :(得分:1)

您可能希望从payments中选择并加入contracts而不是相反的问题?

答案 3 :(得分:1)

你能把你的功能写成

吗?
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']
})