Ответ 1
Ваш лучший вариант:
return Customer.findAll({
attributes: Object.keys(Customer.attributes).concat([
[sequelize.literal('(SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customer"."id")'), 'totalAmount']
])
});
Это выглядит как расширение для выпуска # 1869:
В настоящее время неудачно невозможно выполнить запрос на сквозную модель/таблицу соединений.
Ваш вопрос также касательно связан с этим, где возник вопрос о том, что существует "для каждой таблицы, связанной с пользовательским запросом".
Глядя на тестовый код для предложения include
, я не вижу никаких параметров группы, что является отсутствием доказательств для этого особенность.
Решения:
Конечно, вы можете просто передать запрос "raw":
return sequelize.query(
'SELECT *, (SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customer"."id") AS "totalAmount" FROM "Customers" AS "Customer";',
Customer,
{raw: false}
);
Это даст вам желание, которое вы хотите, и завернуто в экземпляры Customer
.
В качестве альтернативы вы можете добавить метод экземпляра, который возвращает другое обещание:
instanceMethods: {
getOrderSummary: function () {
return Order.findAll({
where: {
CustomerId: this.id
},
attributes: [
[sequelize.fn('SUM', sequelize.col('amount')), 'sum'],
'CustomerId'],
group: ['CustomerId']
});
}
}
Версия метода экземпляра не очень чистая, но она работает нормально и может быть более подходящей в зависимости от вашей ситуации.
Лучшим решением, которое я нашел, является использование литерала SQL в поле attribute
запроса. Единственным недостатком является то, что он, кажется, очищает шифер от выбора других атрибутов, а "*" не режет его. Итак, вам нужно сделать обходной путь с помощью Object.keys()
.
return Customer.findAll({
attributes: Object.keys(Customer.attributes).concat([
[sequelize.literal('(SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customer"."id")'), 'totalAmount']
])
});
Тем не менее, это работает, и вы можете использовать это для некоторых более интересных вложенных SELECT. И это findAll
дает нам правильную:
Executing (default): SELECT "id", "firstName", "lastName", "createdAt", "updatedAt", (SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customer"."id") AS "totalAmount" FROM "Customers" AS "Customer";
{ id: 1,
firstName: 'Test',
lastName: 'Testerson',
createdAt: Wed Feb 04 2015 08:05:42 GMT-0500 (EST),
updatedAt: Wed Feb 04 2015 08:05:42 GMT-0500 (EST),
totalAmount: 15 }
{ id: 2,
firstName: 'Invisible',
lastName: 'Hand',
createdAt: Wed Feb 04 2015 08:05:42 GMT-0500 (EST),
updatedAt: Wed Feb 04 2015 08:05:42 GMT-0500 (EST),
totalAmount: 99 }
Кстати, я также попытался сделать это назад и с помощью GROUP BY в модели Order
выбрать модель Customer
, но это не сработало:
// Doesn't work
return Order.findAll({
attributes: [
[Sequelize.fn('COUNT', '*'), 'orderCount'],
'CustomerId'
],
include: [
{model: Customer, attributes: ['id']}
],
group: ['CustomerId']
});