Sling Academy
Home/Node.js/Understanding GROUP BY in Sequelize.js

Understanding GROUP BY in Sequelize.js

Last updated: December 29, 2023

Introduction

Sequelize is a promise-based Node.js ORM (Object-Relational Mapping) for Postgres, MySQL, MariaDB, SQLite, and Microsoft SQL Server. It features robust transaction support, eager and lazy loading, read replication, and more. GROUP BY is an SQL statement used in conjunction with aggregate functions to group the result-set by one or more columns. This article aims to elucidate the use of the GROUP BY feature within Sequelize.js through progressive examples.

Basic Usage of GROUP BY

The most straightforward way to use GROUP BY in Sequelize is to specify the attributes you want to group by in the group option of a query. Here’s a simple example grouping users by their role:

const User = sequelize.define('user', {
  username: Sequelize.STRING,
  role: Sequelize.STRING
});

User.findAll({
  attributes: ['role'],
  group: ['role']
}).then(groups => {
  console.log(groups);
});

This will produce an output of users grouped by their different roles.

Grouping with Aggregate Functions

Often you need to perform calculations on grouped data using aggregate functions like COUNT, SUM, AVG, etc. Sequelize makes this convenient with its function methods. Here is how you can count the number of users within each role:

const Sequelize = require('sequelize');
const Op = Sequelize.Op;

User.findAll({
  attributes: [[Sequelize.fn('COUNT', Sequelize.col('id')), 'userCount']],
  group : ['role'],
  order: [[Sequelize.fn('COUNT', Sequelize.col('id')), 'DESC']]
}).then(result => {
  console.log(result);
});

The resulting output will provide a count of users for each role, ordered in descending fashion.

Advanced GROUP BY: Joining Tables

When working with related tables, you might want to group data across these relationships. Sequelize offers a powerful way to join tables and group results. Here’s an example where we join a ‘posts’ table to a ‘users’ table and count the number of posts by user:

const Post = sequelize.define('post', {/* ... */});
User.hasMany(Post, { foreignKey: 'userId' });

User.findAll({
  attributes: [
    'username',
    [Sequelize.fn('COUNT', Sequelize.col('posts.id')), 'postCount']
  ],
  include: [{
    model: Post,
    attributes: []
  }],
  group: ['user.id'],
  order: [[Sequelize.fn('COUNT', Sequelize.col('posts.id')), 'DESC']]
}).then(result => {
  console.log(result);
});

In this join, the posts are counted for each user and the result is sorted based on the post count.

Handling GROUP BY with Having

The HAVING clause in SQL is used to specify a search condition for a group. In Sequelize, you can utilise the having option to filter the groups. The following example filters all roles that have a user count greater than 10:

User.findAll({
  attributes: [
    'role',
    [Sequelize.fn('COUNT', Sequelize.col('*')), 'userCount']
  ],
  group: 'role',
  having: Sequelize.where(Sequelize.fn('COUNT', Sequelize.col('*')), '>', 10)
}).then(result => {
  console.log(result);
});

This will return only those roles with more than 10 users associated.

Conclusion

GROUP BY in Sequelize is a flexible and powerful tool that, when combined with aggregate functions, can provide insightful data summaries. As shown in the examples above, you can group your results by one or more fields, compute aggregates like counts, sums, and averages, and even filter groups with the HAVING statement. Understanding GROUP BY will certainly enhance your ability to manipulate and interpret your data effectively using Sequelize.

Next Article: Sequelize.js: Exclude Password from Query Result

Previous Article: How to use Sequelize CLI

Series: Sequelize.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates