J'essaie d'obtenir qu'une telle requête soit générée par séquence:
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";
J'essaie d'éviter la clause GROUP BY
, car j'ai beaucoup de champs à sélectionner et je ne veux pas les regrouper par tous (je pense que ce n'est pas efficace, n'est-ce pas?)
J'ai essayé plusieurs méthodes pour y arriver avec séquençage, notamment {include: ...}
et {attributes: [[...]]}
, mais sans aucune chance.
Des idées? ou peut-être devrais-je utiliser une grosse clause GROUP BY
et laisser tous les champs "normaux" être regroupés?
Votre meilleure option est:
return Customer.findAll({
attributes: Object.keys(Customer.attributes).concat([
[sequelize.literal('(SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customer"."id")'), 'totalAmount']
])
});
Cela ressemble à une extension pour émettre # 1869 :
Interroger sur la table de modèle/joint est actuellement impossible.
Votre question est également liée de manière tangentielle à celle-ci , où la question était une sorte de "pour chaque table associée à une requête d'utilisateur".
En examinant le code de test pour la clause include
, je ne vois aucune option de groupe, ce qui constitue une absence de preuve pour cette fonctionnalité.
Solutions:
Bien sûr, vous pouvez simplement passer la requête "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}
);
Cela vous donnera envie de vouloir, et encapsulé dans des instances Customer
.
Vous pouvez également ajouter une méthode d'instance qui renvoie une autre promesse:
instanceMethods: {
getOrderSummary: function () {
return Order.findAll({
where: {
CustomerId: this.id
},
attributes: [
[sequelize.fn('SUM', sequelize.col('amount')), 'sum'],
'CustomerId'],
group: ['CustomerId']
});
}
}
La version de la méthode d'instance n'est pas très propre, mais elle fonctionne correctement et peut être plus appropriée selon votre situation.
La meilleure solution que j'ai trouvée consiste à utiliser un littéral SQL dans le champ attribute
d'une requête. Le seul inconvénient est qu'il semble effacer l'ardoise lors de la sélection des autres attributs, et qu'un '*' ne le coupe pas. Donc, vous devez faire la solution de contournement avec 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']
])
});
Pourtant, cela fonctionne un charme et vous pouvez l'utiliser pour certains SELECTs imbriqués plus intéressants. Et cette findAll
nous donne le correct:
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 }
D'ailleurs, j'ai aussi essayé de le faire à l'envers et d'utiliser GROUP BY sur le modèle Order
pour le sélectionner dans le modèle Customer
, mais cela n'a pas fonctionné:
// Doesn't work
return Order.findAll({
attributes: [
[Sequelize.fn('COUNT', '*'), 'orderCount'],
'CustomerId'
],
include: [
{model: Customer, attributes: ['id']}
],
group: ['CustomerId']
});
Dans Sequelize 4, vous pouvez ajouter des attributs supplémentaires à l'aide de la syntaxe attributes.include
http://docs.sequelizejs.com/manual/tutorial/querying.html
return Customer.findAll({
attributes: {
include: [
[sequelize.literal('(SELECT SUM("Orders"."amount") FROM "Orders"
WHERE "Orders"."CustomerId" = "Customer"."id")'), 'totalAmount']
]
}
});