当前位置: 首页 > 编程笔记 >

Sequelize中用group by进行分组聚合查询

班宏毅
2023-03-14
本文向大家介绍Sequelize中用group by进行分组聚合查询,包括了Sequelize中用group by进行分组聚合查询的使用技巧和注意事项,需要的朋友参考一下

一、SQL与Sequelize中的分组查询

1.1 SQL中的分组查询

SQL查询中,通GROUP BY语名实现分组查询。GROUP BY子句要和聚合函数配合使用才能完成分组查询,在SELECT查询的字段中,如果没有使用聚合函数就必须出现在ORDER BY子句中。分组查询后,查询结果为一个或多个列分组后的结果集。

GROUP BY语法

SELECT 列名, 聚合函数(列名)
FROM 表名
WHERE 列名 operator value
GROUP BY 列名 
[HAVING 条件表达式] [WITH ROLLUP]

在以上语句中:

聚合函数 - 分组查询通常要与聚合函数一起使用,聚合函数包括:

  •      COUNT()-用于统计记录条数
  •      SUM()-用于计算字段的值的总和
  •      AVG()-用于计算字段的值的平均值
  •      MAX-用于查找查询字段的最大值
  •      MIX-用于查找查询字段的最小值

GROUP BY子名-用于指定分组的字段

HAVING子名-用于过滤分组结果,符合条件表达式的结果将会被显示

WITH ROLLUP子名-用于指定追加一条记录,用于汇总前面的数据

1.2 Sequelize中的分组查询

使用聚合函数

Sequelize提供了聚合函数,可以直接对模型进行聚合查询:

  1. aggregate(field, aggregateFunction, [options])-通过指定的聚合函数进行查询
  2. sum(field, [options])-求和
  3. count(field, [options])-统计查询结果数
  4. max(field, [options])-查询最大值
  5. min(field, [options])-查询最小值

以上这些聚合函数中,可以通过options.attributes、options.attributes属性指定分组相关字段,并可以通过options.having指定过滤条件,但没有直接指定WITH ROLLUP子句的参数。

如,使用.sum()查询订单数量大于1的用户订单额:

Order.sum('price', {attributes:['name'], group:'name', plain:false, having:['COUNT(?)>?', 'name', 1]}).then(function(result){
 console.log(result);
})

生成的SQL语句如下:

SELECT `name`, sum(`price`) AS `sum` FROM `orders` AS `Orders` GROUP BY name HAVING COUNT('name')>1;

使用聚合参数

除直接使用聚合函数外,也可以在findAll()等方法中,指定聚合查询相关参数实现聚合查询。查询时,同样可以通过通过options.attributes、options.attributes属性指定分组相关字段,并可以通过options.having指定过滤条件。与直接使用聚合函数查询不一样,通过参数构建聚合查询时,要以数组对象形式设置options.attributes参数中的聚合字段,并需要通过sequelize.fn()方法传入聚合函数。

如,使用.findAll()查询订单数量大于1的用户订单额:

Order.findAll({attributes:['name', [sequelize.fn('SUM', sequelize.col('price')), 'sum']], group:'name', having:['COUNT(?)>?', 'name', 1], raw:true}).then(function(result){
 console.log(result);
})

生成的SQL语句如下:

SELECT `name`, sum(`price`) AS `sum` FROM `orders` AS `Orders` GROUP BY name HAVING COUNT('name')>1;

二、使用示例

现在订单表,数据如下:

> select * from orders;
+---------+-------------+--------+-----------+---------------------+
| orderId | orderNumber | price | name  | createdOn   |
+---------+-------------+--------+-----------+---------------------+
|  1 | 00001  | 128.00 | 张小三 | 2016-11-25 10:12:49 |
|  2 | 00002  | 102.00 | 张小三 | 2016-11-25 10:12:49 |
|  4 | 00004  | 99.00 | 王小五 | 2016-11-25 10:12:49 |
|  3 | 00003  | 199.00 | 赵小六 | 2016-11-25 10:12:49 |
+---------+-------------+--------+-----------+---------------------+

2.1 简单使用

使用分组查询,统计每个客户的订单总额。

使用SQL语句,可以像下面这样查询:

> select name, SUM(price) from orders GROUP BY name;
+-----------+------------+
| name  | SUM(price) |
+-----------+------------+
| 张小三 |  230.00 |
| 王小五 |  99.00 |
| 赵小六 |  199.00 |
+-----------+------------+

而在Sequelize中可以像下面这样实现:

Order.findAll({attributes:['sum', [sequelize.fn('SUM', sequelize.col('name')), 'sum']], group:'name', raw:true}).then(function(result){
 console.log(result);
})

2.2 使用HAVING子句

统计订单数量大于1的用户的订单总金额。

使用SQL语句,可以像下面这样实现:

> select name, SUM(price) from orders GROUP BY name HAVING count(1)>1;
+-----------+------------+
| name  | SUM(price) |
+-----------+------------+
| 张小三 |  230.00 |
| 赵小六 |  199.00 |
+-----------+------------+

而使用Sequelize可以像下面这样查询:

Order.findAll({attributes:['sum', [sequelize.fn('SUM', sequelize.col('name')), 'sum']], group:'name', having:['COUNT(?)>?', 'name', 1], raw:true}).then(function(result){
 console.log(result);
})

2.3 使用WITH ROLLUP子句

WITH ROLLUP子句是MySQL 5.5+新增的特性,用于汇总统计结果。但本文发布时,Sequelize还不支持该特性。

增加总和统计列:

> select name, SUM(price) from orders GROUP BY name WITH ROLLUP;
+-----------+------------+
| name  | SUM(price) |
+-----------+------------+
| 张小三 |  230.00 |
| 王小五 |  99.00 |
| 赵小六 |  199.00 |
| NULL  |  528.00 |
+-----------+------------+

2.4 连接查询与分组

为了管理方便,我们会将不同的信息保存在不同的表中。如,我们会将订单信息放在一张表中,而将客户信息保存在另一张表中。对于存在关联关系的两张表,我们会使用连接查询来查找关联数据,在进行连接查询时,同样可以以使用聚合函数。

订单表如下:

> select * from orders;
+---------+-------------+--------+------------+---------------------+
| orderId | orderNumber | price | customerId | createdOn   |
+---------+-------------+--------+------------+---------------------+
|  1 | 00001  | 128.00 |   1 | 2016-11-25 10:12:49 |
|  2 | 00002  | 102.00 |   1 | 2016-11-25 10:12:49 |
|  3 | 00003  | 199.00 |   4 | 2016-11-25 10:12:49 |
|  4 | 00004  | 99.00 |   3 | 2016-11-25 10:12:49 |
+---------+-------------+--------+------------+---------------------+

客户表结构如下:

> select * from customers;
+----+-----------+-----+---------------------+---------------------+
| id | name  | sex | birthday   | createdOn   |
+----+-----------+-----+---------------------+---------------------+
| 1 | 张小三 | 1 | 1986-01-22 08:00:00 | 2016-11-25 10:16:35 |
| 2 | 李小四 | 2 | 1987-11-12 08:00:00 | 2016-11-25 10:16:35 |
| 3 | 王小五 | 1 | 1988-03-08 08:00:00 | 2016-11-25 10:16:35 |
| 4 | 赵小六 | 1 | 1989-08-11 08:00:00 | 2016-11-25 10:16:35 |
+----+-----------+-----+---------------------+---------------------+

使用连接查询并分组查询,统计每个客户的订单总额。

使用SQL语句查询如下:

> select c.name, SUM(o.price) AS sum from customers AS c INNER JOIN orders AS o ON o.customerId =c.id GROUP BY c.name;

Sequelize中进行连接查询时,首先需要建立模型间的关联关系:

Order.belongsTo(Customer, {foreignKey: 'customerId'});

连接查询及分组:

var include = [{
 model: Customer,
 required: true,
 attributes: ['name'],
}]
Order.findAll({include:include, attributes:[[sequelize.fn('SUM', sequelize.col('price')), 'sum']], group:'Customer.name', having:['COUNT(?)>?', 'name', 1], raw:true, rollup:true}).then(function(result){
 console.log(result);
})

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

 类似资料:
  • 我的模式实现受到了mongo官方网站上这篇教程的影响 这基本上是为时间序列数据设计的模式,我将每个设备每小时的数据存储在单个文档中的数组中。我创建字段组合发送数据和时间的设备id。例如,如果id为的设备在发送数据,则我的 字段将变为

  • 我有一个复杂的组查询。 数据如下: 汇总如下: null

  • 如何执行SQL查询以根据特定列的给定值对行进行分组。例如,假设我们有一个表1 并且希望得到另一个带有值的表2的查询 并且我希望有一个结果表,对给定ID之前的行进行分组。所以像这样的事情 不确定是否应该称之为分组,它更像是一个从开始到特定行/ID的连接/聚合结果。

  • 按组合并返回结果 1,比如菜单服务,接口一样,但有多种实现,用group区分,现在消费方需从每种group中调用一次返回结果,合并结果返回,这样就可以实现聚合菜单项。 相关代码可以参考 dubbo 项目中的示例 配置 搜索所有分组 <dubbo:reference interface="com.xxx.MenuService" group="*" merger="true" /> 合并指定分组

  • 假设我有一个MongoDB集合,其中包含以下信息: 我想计算按州分组的订单总价的总和,其中项目为“苹果”,颜色为“红色”。我的问题是: 但是,我希望能够将我的结果cust\u id包含在\u id中,它是一个数组/映射/一些结构,其中包含构成我的合计的所有客户id的列表。因此,我希望我的输出包含 是否有办法处理此mongo聚合/查询?或者是一种更好的方式来构造此查询,以便我可以按州分组计算红苹果的

  • 设想一个集合,该集合在聚合的$match操作符上返回具有此结构的文档数组 所以基本上每个返回的文档都共享一个片段(这就是我将如何对它们进行分组),但是每个文档都有一个子文档数组,每个子文档都有不同的_id。 因此,当我使用{slug:“a”}执行$match聚合时,它返回一个数组