私はそのようなクエリを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: ...}
と{attributes: [[...]]}
を含めましたが、うまくいきませんでした。
何か案は?または、1つの大きなGROUP BY
句を使用して、すべての「通常の」フィールドをグループ化する必要がありますか?
あなたの最良の選択肢は:
_ return Customer.findAll({
attributes: Object.keys(Customer.attributes).concat([
[sequelize.literal('(SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customer"."id")'), 'totalAmount']
])
});
_
これは、拡張機能のようです #1869 :
残念ながら、現在、モデル/結合テーブルを介したクエリは実行できません。
あなたの質問はまた、接線的に this one に関連しています。ここで、質問は、「ユーザークエリに関連付けられたテーブルごと」のようなものでした。
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
インスタンスにラップされます。
または、別のpromiseを返すインスタンスメソッドを追加することもできます。
_instanceMethods: {
getOrderSummary: function () {
return Order.findAll({
where: {
CustomerId: this.id
},
attributes: [
[sequelize.fn('SUM', sequelize.col('amount')), 'sum'],
'CustomerId'],
group: ['CustomerId']
});
}
}
_
インスタンスメソッドのバージョンはあまりきれいではありませんが、問題なく動作し、状況によってはより適切な場合があります。
私が見つけた最良の解決策は、クエリのattribute
フィールドでSQLリテラルを使用することです。唯一の欠点は、他の属性を選択するとスレートが完全に消去されるように見えることと、「*」ではそれが切り取られないことです。したがって、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 }
_
ところで、私はそれを逆にして、Order
モデルでGROUP BYを使用してCustomer
モデルを選択することも試みましたが、うまくいきませんでした:
_ // Doesn't work
return Order.findAll({
attributes: [
[Sequelize.fn('COUNT', '*'), 'orderCount'],
'CustomerId'
],
include: [
{model: Customer, attributes: ['id']}
],
group: ['CustomerId']
});
_
Sequelize 4では、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']
]
}
});