How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: How to Count Records Grouped By a Column in Laravel Eloquent
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Learn > Web Development > How to Count Records Grouped By a Column in Laravel Eloquent
Web Development

How to Count Records Grouped By a Column in Laravel Eloquent

how7o
By how7o
Last updated: April 20, 2026
7 Min Read
Laravel Eloquent group by count — Book::groupBy('author') query with bar-chart aggregate icon
SHARE

Grouping records by a column and counting each group is a classic report query — “how many books per author”, “how many orders per status”, “how many users per country”. In Laravel the fluent builder makes laravel eloquent group by count a short chain: groupBy() plus a raw count(*) in the select list. This guide shows the exact pattern, the ONLY_FULL_GROUP_BY strict-mode pitfall that trips a lot of people up, and how to filter groups with havingRaw().

Contents
  • TL;DR
  • Basic grouped-count query
  • The ONLY_FULL_GROUP_BY pitfall
    • Fix 1 — align SELECT and GROUP BY
    • Fix 2 — disable strict mode for this connection
  • Filtering groups with HAVING
  • Collection-based grouping (small tables only)
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-04-21 on Laravel 11 with PHP 8.3 and MySQL 8.0. Originally published 2023-02-07, rewritten and updated 2026-04-21.

TL;DR

Combine select('col', DB::raw('count(*) as total')) with groupBy('col') to get one row per distinct value of col plus a total column. Every non-aggregate column in the SELECT list must also appear in the groupBy() list under MySQL’s default strict mode. Use havingRaw() to filter groups.

Basic grouped-count query

Here is the canonical “books per author” query. Select the grouping column, add a raw count(*) aggregate with a friendly alias, and call groupBy() on the same column:

$books = Book::groupBy('author')
    ->select('author', DB::raw('count(*) as total'))
    ->get();

foreach ($books as $book) {
    echo "Author " . $book->author . " - " . $book->total . " books";
}

Compiled SQL:

SELECT author, count(*) as total FROM books GROUP BY author

The loop has access to the two aliases — $book->author and $book->total — even though those aren’t real model attributes from the books table schema. The result is an Eloquent collection of “pseudo-models” that exist only for the duration of the query.

The ONLY_FULL_GROUP_BY pitfall

The single most common error on a fresh MySQL 5.7+ or 8.x install looks like this:

SQLSTATE[42000]: Syntax error or access violation: 1055
Expression #N of SELECT list is not in GROUP BY clause
and contains nonaggregated column ... which is not functionally dependent
on columns in GROUP BY clause; this is incompatible with
sql_mode=only_full_group_by

It fires when your SELECT list includes a non-aggregated column that isn’t in the GROUP BY list. Two fixes:

Fix 1 — align SELECT and GROUP BY

Preferred. Add every non-aggregate selected column to the groupBy() list, or wrap it in an aggregate if you want a representative value:

Book::select('author', 'language', DB::raw('count(*) as total'))
    ->groupBy('author', 'language')
    ->get();

// or wrap in MAX() when the column shouldn't be part of the grouping:
Book::select('author', DB::raw('MAX(published_at) as latest'), DB::raw('count(*) as total'))
    ->groupBy('author')
    ->get();

Fix 2 — disable strict mode for this connection

If aligning the lists isn’t practical (legacy queries, shared code), turn strict mode off in config/database.php for the MySQL connection:

'mysql' => [
    // ...
    'strict' => false,
],

That removes ONLY_FULL_GROUP_BY (and other strict-mode flags) from the session. Use it as an escape hatch, not a default — the strict mode exists because GROUP BY with unlisted columns returns non-deterministic values and masks real bugs.

laravel eloquent group by count — groupBy + count(*) + havingRaw filter flow

Filtering groups with HAVING

WHERE filters rows before grouping; HAVING filters groups after. To show only authors with more than one book:

$books = Book::select('author', DB::raw('count(*) as total'))
    ->groupBy('author')
    ->havingRaw('count(*) > ?', [1])
    ->get();

Because total is declared as an alias in the SELECT list, you can also use the fluent form against the alias:

->having('total', '>', 1)

Collection-based grouping (small tables only)

Laravel collections have their own groupBy() that works entirely in PHP:

$perAuthor = Book::all()->groupBy('author')->map->count();
// $perAuthor is a keyed collection: ['Tolkien' => 3, 'Orwell' => 2, ...]

The syntax is terse and useful for small, already-in-memory collections. Do not use it on large tables — Book::all() loads every row, then PHP does the grouping work. The query-builder version pushes everything to MySQL and scales.

Frequently asked questions

Why do I get “SQLSTATE[42000] … only_full_group_by” errors?

MySQL 5.7+ enables ONLY_FULL_GROUP_BY strict mode by default, which requires every non-aggregated column in the SELECT list to appear in the GROUP BY clause. Either add the missing columns to groupBy(), wrap them in an aggregate like MAX(), or set 'strict' => false in config/database.php to disable the mode for that connection.

How do I filter groups by their count (HAVING clause)?

Use havingRaw() for count-based conditions: Book::select('author', DB::raw('count(*) as total'))->groupBy('author')->havingRaw('count(*) > ?', [1])->get(). That returns only authors with more than one book. You can also use the fluent having('total', '>', 1) since total is a declared alias in the SELECT.

Should I use groupBy() on the query or on the collection?

Almost always on the query. Book::all()->groupBy('author')->map->count() works and reads nicely, but it loads every row into PHP first — fine for small tables, terrible once you’re past a few thousand rows. The query-builder form pushes the work to MySQL and returns just the aggregated rows.

Can I group by multiple columns?

Yes — pass multiple column names to groupBy(): Book::select('author', 'language', DB::raw('count(*) as total'))->groupBy('author', 'language')->get(). Every selected non-aggregate column must be in the groupBy list (strict mode), which is another reason the SELECT and GROUP BY drift tends to cause errors.

How do I access both grouped columns and the count in Blade?

The select aliases become properties on each result row. With select('author', DB::raw('count(*) as total')), the loop gives you $row->author and $row->total. If you’d rather work with an Eloquent model instance, skip the groupBy aggregate and use withCount('books') on the parent model instead.

Related guides

  • How to Install Laravel on Ubuntu — set up the framework before writing aggregate queries.
  • Best Way to Insert or Update Records in Laravel Eloquent — another single-query aggregate pattern.
  • How to Add Foreign Keys in Laravel Migration — relevant when grouping across a parent relationship.

References

Query-builder grouping, having, and raw expressions: laravel.com/docs/queries. Eloquent aggregates and withCount: laravel.com/docs/eloquent.

TAGGED:EloquentLaravelmysqlphpsqltroubleshooting

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article Laravel Eloquent count rows — Post::count query snippet with aggregate bar chart icon How to Count Rows in Laravel Eloquent Efficiently
Next Article Laravel Eloquent current month records — calendar and query builder illustration How to Get Current Month Records in Laravel Eloquent
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Display PHP errors — ini_set + php.ini configuration
How to Display PHP Errors
May 10, 2026
PHP convert string to uppercase — strtoupper and mb_strtoupper
How to Convert a String to Uppercase in PHP
May 10, 2026
PHP string to float conversion with cast, regex cleanup, NumberFormatter
How to Convert a String to Float in PHP
May 10, 2026
PHP merge arrays without duplicates — union operator and array_unique
How to Combine Two Arrays Without Duplicates in PHP
May 10, 2026
PHP delete array element — unset, array_splice, array_filter, array_search
How to Delete an Element from a PHP Array
May 10, 2026

You Might Also Like

Laravel Eloquent exists method checking if a record exists in a database query
Web Development

How to Check if a Record Exists in Laravel

6 Min Read
MySQL remove string from column — REPLACE and REGEXP_REPLACE patterns
Web Development

How to Remove a Specific String from a Column in MySQL

6 Min Read
Laravel DataTables HTML column — rawColumns opt-out of the default escaping
Web Development

How to Add an HTML Column in Laravel DataTables

7 Min Read
WordPress posts by date range — date_query with after/before/inclusive
Web Development

How to Get Posts by Date Range in WordPress

7 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?