подзапрос sequelize как поле
Я пытаюсь получить такой запрос, который будет сгенерирован sequlized:
SELECT
"Customers"."id",
(SELECT SUM("Orders"."amount") FROM "Orders"
WHERE "Orders"."CustomerId" = "Customers"."id") AS "totalAmount",
"Customer"."lastName" AS "Customer.lastName",
"Customer"."firstName" AS "Customer.firstName"
FROM "Customers" AS "Customer";
Я пытаюсь избежать GROUP BY
предложение, так как у меня есть много полей для выбора, и я не хочу группировать их по всем (я думаю, что это не эффективно, не так ли?)
Я пробовал несколько способов сделать это с sequelize, include {include: ...}
и {attributes: [[...]]}
, но без каких-либо удачи.
какие идеи? или, может быть, я должен использовать один большой GROUP BY
предложение и пусть все "регулярные" поля будут сгруппировать по?
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:
запрос на сквозную таблицу model / join в настоящее время невозможен, к сожалению.
ваш вопрос также тангенциально связан с этот, где вопрос был своего рода "для каждого запроса пользователя, связанного с таблицей".
смотреть на!--29-->тестовый код для 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']
])
});
тем не менее, он работает шарм, и вы можете использовать это для более интересных вложенных вариантов. И это 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 }
кстати, я также попытался сделать это назад и использовать группу на Order
модель для выбора в Customer
модель, но это не сработало:
// Doesn't work
return Order.findAll({
attributes: [
[Sequelize.fn('COUNT', '*'), 'orderCount'],
'CustomerId'
],
include: [
{model: Customer, attributes: ['id']}
],
group: ['CustomerId']
});