在 sequelize 中使用 group by 和 joins

Posted

技术标签:

【中文标题】在 sequelize 中使用 group by 和 joins【英文标题】:Using group by and joins in sequelize 【发布时间】:2015-03-28 04:54:36 【问题描述】:

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

我没有要求选择 payment.id,因为我必须将它包含在我的聚合或分组函数中,正如我遇到的错误中所说:

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

我在这里遗漏了什么吗?我正在关注this answer,但即使在那里我也不明白 SQL 请求如何有效。

【问题讨论】:

【参考方案1】:

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

【讨论】:

【参考方案2】:

你能把你的函数写成

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']
)

【讨论】:

您的意思是 'contracts.id' 而不是 'models.contracts.id' 吗?无论如何,第一个给我同样的错误,第二个抛出另一个 SQL 错误(缺少 FROM 子句)。【参考方案3】:

试试

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

【讨论】:

谢谢,但如果我按 'payments.id' 分组,我将无法汇总 payment.payment_amount。 attributes: ['payment_amount', [models.sequelize.fn('sum', models.sequelize.col('payments.payment_amount')), 'total_cost']] 怎么样。如果选择“nothing”,基本上sequelize 会选择id。如果可行,我将更新我的答案。希望是的。 不幸的是,总是同样的错误:Possibly unhandled SequelizeDatabaseError: column "payments.id" must appear in the GROUP BY clause or be used in an aggregate function【参考方案4】:

此问题已在 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']
)

【讨论】:

以上是关于在 sequelize 中使用 group by 和 joins的主要内容,如果未能解决你的问题,请参考以下文章

Sequelize GROUP BY 仅在主表上聚合,而不是连接中的完整连接表

在 Sequel Pro 中禁用严格模式

怎么使用group by?

在summarize()中使用group_by()的语法[关闭]

聚合函数 和 group by

如何在 TensorFlow 中使用“group_by_window”函数