Question

How do you use CakePHP 4 to perform a select count with distinct and group by?

Answer and Explanation

To perform a SELECT COUNT with DISTINCT and GROUP BY in CakePHP 4, you can leverage the Query Builder. Here's how you can achieve this:

Let's assume you have a table named 'users' and you want to count the distinct number of users based on their 'city' and 'country'.

1. Using the Query Builder:

- You'll use the find() method on your Table object and then chain methods to build your query.

2. Example Code:

<?php
namespace App\Controller;

use Cake\ORM\TableRegistry;
use Cake\Controller\Controller;

class UsersController extends Controller
{
  public function countUsersByLocation()
  {
    $usersTable = TableRegistry::getTableLocator()->get('Users');

    $query = $usersTable->find()
        ->select(['city', 'country', 'user_count' => $query->func()->count('DISTINCT id')])
        ->group(['city', 'country'])
        ->order(['country' => 'ASC', 'city' => 'ASC']);

    $results = $query->toArray();

    $this->set(compact('results'));
  }
}
?>

3. Explanation:

- TableRegistry::getTableLocator()->get('Users'): Gets the 'Users' table object.

- $usersTable->find(): Starts a new query.

- ->select(['city', 'country', 'user_count' => $query->func()->count('DISTINCT id')]): Selects the 'city', 'country', and a count of distinct user IDs, aliased as 'user_count'.

- ->group(['city', 'country']): Groups the results by 'city' and 'country'.

- ->order(['country' => 'ASC', 'city' => 'ASC']): Orders the results by 'country' and then 'city' in ascending order.

- $query->toArray(): Executes the query and fetches the results as an array.

4. Important Notes:

- Make sure to replace 'Users' with the actual name of your table.

- The $query->func()->count('DISTINCT id') part is crucial for getting the distinct count.

- You can adjust the fields in select(), group(), and order() to match your specific requirements.

This approach provides a clean and efficient way to perform complex SQL queries using CakePHP 4's Query Builder.

More questions