Sequelize - Подсчет одной и той же ассоциации дважды в разных условиях - PullRequest
0 голосов
/ 20 сентября 2018

Я пытаюсь получить два числа записей в связанной таблице на основе разных параметров:

// Models
var Customer = sequelize.define('Customer', {
    name: DataTypes.STRING,
});
var Invoice = sequelize.define('Invoice', {
    invoiceRef: DataTypes.STRING,
    status: {
        type: DataTypes.ENUM,
        values: ['UNPAID', 'PAID'],
        defaultValue: 'UNPAID'
    },
    isArchived: {
        type: DataTypes.BOOLEAN,
        defaultValue: false
    },
});
Invoice.associate = function(models) {
    Invoice.belongsTo(models.Customer);
}
Customer.associate = function (models) {
    Customer.hasMany(models.Invoice);
}


// Query
Customer.findAll({
    attributes: {
        include: [
            [models.Sequelize.fn("COUNT", models.Sequelize.fn("DISTINCT", models.Sequelize.col("Invoices.id"))), "totalInvoices"],
            [models.Sequelize.fn("COUNT", models.Sequelize.fn("DISTINCT", models.Sequelize.col("UnpaidInvoices.id"))), "unpaidInvoices"]
        ]
    },
    include: [
        {
            model: models.Invoice,
            where: { isArchived: false },
            attributes: [],
            required: false
        },
        {
            model: models.Invoice,
            where: { isArchived: false, status: 'UNPAID' },
            attributes: [],
            required: false
        },
    ],
    group: ['Customer.id']
})

Проблема заключается в том, что при многократном включении одной и той же связанной таблицы Sequelize назначает одно и то же имяоба экземпляра таблицы в запросе SQL:

ВЛЕВО НАРУЖНОЕ СОЕДИНЕНИЕ Invoices AS Invoices ON Customer. id = Invoices. CustomerId AND Invoices.isArchived = 0
ВЛЕВО НАРУЖНОЕ СОЕДИНЕНИЕ Invoices AS Invoices ВКЛ Customer. id = Invoices. CustomerId И Invoices. isArchived = 0 И Invoices. status = 'UNPAID'

Можно ли указать другое имя для использования в объединенной таблице в запросе?Например:

ВЛЕВО НАРУЖНОЕ СОЕДИНЕНИЕ Invoices AS Invoices ВКЛ Customer. id = Invoices. CustomerId И Invoices. isArchived = 0
LEFT OUTER JOIN Invoices AS UnpaidInvoices ON Customer. id = Invoices. CustomerId И Invoices. isArchived = 0 И Invoices. status = 'НЕоплаченный'

1 Ответ

0 голосов
/ 22 сентября 2018

Обычно я просто присоединяюсь один раз, а затем использую оператор CASE с SUM вместо COUNT - все строки объединяются, поэтому вы получаете одно и то же для обоих.

attributes: {
  include: [
    // count paid using case/sum via `status` != 'UNPAID'
    [ sequelize.fn('sum', sequelize.literal("CASE WHEN (`Invoices`.`status` != 'UNPAID' THEN 1 ELSE 0 END")), 'paid_count' ],
    // count unpaid using case/sum via `status` = 'UNPAID'
    [ sequelize.fn('sum', sequelize.literal("CASE WHEN (`Invoices`.`status` = 'UNPAID' THEN 1 ELSE 0 END")), 'unpaid_count' ],
  ],
  // ...
},
...