Sequelize.js 将子查询续写为字段

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"

我试图让Sequalized生成这样的查询:

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']
        ]
    }
});