Sequelize.js 将子查询续写为字段
我试图让Sequalized生成这样的查询:Sequelize.js 将子查询续写为字段,sequelize.js,Sequelize.js,我试图让Sequalized生成这样的查询: SELECT "Customers"."id", (SELECT SUM("Orders"."amount") FROM "Orders" WHERE "Orders"."CustomerId" = "Customers"."id") AS "totalAmount", "Customer"."lastName" AS "Customer.lastName", "Customer"."firstName"
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";
我试图避免使用groupby
子句,因为我有很多字段要选择,而且我不想按所有字段分组(我认为这不是很有效,不是吗?)
我用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']
])
});
这看起来像是问题的扩展: 目前无法通过模型/联接表进行查询 您的问题也与相关联,其中的问题有点像“for each user query associated table” 查看
include
子句的列表,我没有看到任何组选项,这是因为缺少此功能的证据
解决方案:
当然,您可以传递查询“raw”:
这将提供您想要的,并包装到Customer
实例中
或者,您可以添加一个实例方法,该方法返回另一个承诺:
instanceMethods: {
getOrderSummary: function () {
return Order.findAll({
where: {
CustomerId: this.id
},
attributes: [
[sequelize.fn('SUM', sequelize.col('amount')), 'sum'],
'CustomerId'],
group: ['CustomerId']
});
}
}
实例方法版本不是很干净,但它可以正常工作,并且可能更适合您的情况
我发现的最好的解决方案是在查询的属性
字段中使用SQL文本。唯一的缺点是,它似乎在选择其他属性时一笔勾销,而“*”并不能解决这个问题。因此,您需要使用Object.keys()
进行变通
尽管如此,它还是很有魅力,你可以用它来做一些更有趣的嵌套选择。这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中,您可以使用
属性添加额外的属性
酷。我必须使其适应我的用例,但它似乎解决了我当前的问题。10x.调用对象.keys(Customer.attributes).concat()
调用得很好。尽管*
,我还是不明白为什么其他属性没有显示出来。对于稍后阅读本文的读者,@srlm创建了一篇很好的博客文章,清楚地解释了这一点,包括对实例方法的详细阐述。请注意,在当前的Sequelize中,由于某种难以理解的原因,模型上的属性
字段已重命名为rawtattributes
。因此,您必须执行Customer.rawtattributes
。它被添加到查询中,但如何访问它?您应该能够将它作为返回实例上的一个属性来访问,例如,如果您有来自上述查询(返回一个客户数组)的客户,Customer.totalAmount
,但如果这不起作用,请尝试Customer.get('totalAmount')
或Customer.dataValues('totalAmount')
。谢谢您的帮助。
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 }
// Doesn't work
return Order.findAll({
attributes: [
[Sequelize.fn('COUNT', '*'), 'orderCount'],
'CustomerId'
],
include: [
{model: Customer, attributes: ['id']}
],
group: ['CustomerId']
});
return Customer.findAll({
attributes: {
include: [
[sequelize.literal('(SELECT SUM("Orders"."amount") FROM "Orders"
WHERE "Orders"."CustomerId" = "Customer"."id")'), 'totalAmount']
]
}
});