sequelize 子查询作为字段
sequelize subquery as field
我正在尝试通过 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
子句,因为我有很多字段需要 select 并且我不想按所有字段分组(我认为这效率不高,是吗?不是吗?)
我已经尝试了几种方法来实现 sequelize,包括 {include: ...}
和 {attributes: [[...]]}
,但没有任何运气。
有什么想法吗?或者也许我应该使用一个大的 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:
的扩展
Querying on the through model/join table is not possible currently unfortuneatly.
您的问题也与 this one 无关,其中的问题有点像“对于每个关联的用户查询 table”。
查看 test code 的 include
子句,我没有看到任何组选项,这表明此功能没有证据。
解决方案:
当然,您可以只传递“原始”查询:
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
个实例。
或者,您可以添加一个 returns 另一个承诺的实例方法:
instanceMethods: {
getOrderSummary: function () {
return Order.findAll({
where: {
CustomerId: this.id
},
attributes: [
[sequelize.fn('SUM', sequelize.col('amount')), 'sum'],
'CustomerId'],
group: ['CustomerId']
});
}
}
实例方法版本不是很干净,但它工作正常,可能更适合您的情况。
我发现的最佳解决方案是在查询的 attribute
字段中使用 SQL 文字。唯一的缺点是它似乎在 selecting 其他属性上将石板擦干净,并且'*'不会削减它。因此,您需要使用 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 select 进入 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']
]
}
});
我正在尝试通过 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
子句,因为我有很多字段需要 select 并且我不想按所有字段分组(我认为这效率不高,是吗?不是吗?)
我已经尝试了几种方法来实现 sequelize,包括 {include: ...}
和 {attributes: [[...]]}
,但没有任何运气。
有什么想法吗?或者也许我应该使用一个大的 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:
的扩展Querying on the through model/join table is not possible currently unfortuneatly.
您的问题也与 this one 无关,其中的问题有点像“对于每个关联的用户查询 table”。
查看 test code 的 include
子句,我没有看到任何组选项,这表明此功能没有证据。
解决方案:
当然,您可以只传递“原始”查询:
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
个实例。
或者,您可以添加一个 returns 另一个承诺的实例方法:
instanceMethods: {
getOrderSummary: function () {
return Order.findAll({
where: {
CustomerId: this.id
},
attributes: [
[sequelize.fn('SUM', sequelize.col('amount')), 'sum'],
'CustomerId'],
group: ['CustomerId']
});
}
}
实例方法版本不是很干净,但它工作正常,可能更适合您的情况。
我发现的最佳解决方案是在查询的 attribute
字段中使用 SQL 文字。唯一的缺点是它似乎在 selecting 其他属性上将石板擦干净,并且'*'不会削减它。因此,您需要使用 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 select 进入 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']
]
}
});