Repository: codeigniter4/CodeIgniter4 (PHP)

Issue:
Bug: Can't paginate query with group by
For example, I have the following SQL: 

```sql
SELECT `album`.*, 
             COUNT(track.id) as total_song 
             FROM `album` 
                 LEFT JOIN 
            `track` 
                 ON `album`.`id` = `track`.`album_id` 
           GROUP BY `album`.`id`;
```

For example, I use `model(Album::class)->paginate()`, the pagination is using query to get total num rows: 

```sql
SELECT COUNT(*) AS `numrows`
             FROM `album` 
                 LEFT JOIN 
            `track` 
               ON `album`.`id` = `track`.`album_id` 
            GROUP BY `album`.`id`
```

Which the `numrows` results multiple rows for getting total rows which make data total rows incorrect.

For workaround, I modify the query with non-group by query: 

```sql
SELECT 
    *,
   (SELECT count(*) FROM `track` WHERE `album_id` = `album`.`id`) AS total_song 
   FROM `album` 
```

**CodeIgniter 4 version**
4.0.2

**Expected behavior, and steps to reproduce if appropriate**
Show correct total numrows

**Context**
 - OS: OSX
 - Web server Apache
 - PHP version 7.4.4



Discussion:
The query of getting numrows of `model()->paginate()` when there is a group by needs to be updated like : 

```sql
select COUNT(*) as numrows from 
      (
            SELECT `album`.*, 
                 COUNT(track.id) as total_song FROM `album` 
                       LEFT JOIN `track` ON `album`.`id` = `track`.`album_id` 
                   GROUP BY `album`.`id`
       ) as album 
```
I've created PR #2777 for it.



Patch:
diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php
index 1237aa0135b1..b9d34d990ccb 100644
--- a/system/Database/BaseBuilder.php
+++ b/system/Database/BaseBuilder.php
@@ -1921,7 +1921,7 @@ public function countAllResults(bool $reset = true)
 		$limit         = $this->QBLimit;
 		$this->QBLimit = false;
 
-		$sql = ($this->QBDistinct === true)
+		$sql = ($this->QBDistinct === true || ! empty($this->QBGroupBy))
 			?
 			$this->countString . $this->db->protectIdentifiers('numrows') . "\nFROM (\n" . $this->compileSelect() . "\n) CI_count_all_results"
 			:


Test patch:
diff --git a/tests/system/Database/Builder/CountTest.php b/tests/system/Database/Builder/CountTest.php
index 0f0496ba5aa2..b5ef4dbac7e0 100644
--- a/tests/system/Database/Builder/CountTest.php
+++ b/tests/system/Database/Builder/CountTest.php
@@ -43,4 +43,50 @@ public function testCountAllResults()
 	}
 
 	//--------------------------------------------------------------------
+
+	public function testCountAllResultsWithGroupBy()
+	{
+		$builder = new BaseBuilder('jobs', $this->db);
+		$builder->groupBy('id');
+		$builder->testMode();
+
+		$answer = $builder->where('id >', 3)->countAllResults(false);
+
+		$expectedSQL = 'SELECT COUNT(*) AS "numrows" FROM ( SELECT * FROM "jobs" WHERE "id" > :id: GROUP BY "id" ) CI_count_all_results';
+
+		$this->assertEquals($expectedSQL, str_replace("\n", ' ', $answer));
+	}
+
+	//--------------------------------------------------------------------
+
+	public function testCountAllResultsWithGroupByAndHaving()
+	{
+		$builder = new BaseBuilder('jobs', $this->db);
+		$builder->groupBy('id');
+		$builder->having('1=1');
+		$builder->testMode();
+
+		$answer = $builder->where('id >', 3)->countAllResults(false);
+
+		$expectedSQL = 'SELECT COUNT(*) AS "numrows" FROM ( SELECT * FROM "jobs" WHERE "id" > :id: GROUP BY "id" HAVING 1 = 1 ) CI_count_all_results';
+
+		$this->assertEquals($expectedSQL, str_replace("\n", ' ', $answer));
+	}
+
+	//--------------------------------------------------------------------
+
+	public function testCountAllResultsWithHavingOnly()
+	{
+		$builder = new BaseBuilder('jobs', $this->db);
+		$builder->having('1=1');
+		$builder->testMode();
+
+		$answer = $builder->where('id >', 3)->countAllResults(false);
+
+		$expectedSQL = 'SELECT COUNT(*) AS "numrows" FROM "jobs" WHERE "id" > :id: HAVING 1 = 1';
+
+		$this->assertEquals($expectedSQL, str_replace("\n", ' ', $answer));
+	}
+
+	//--------------------------------------------------------------------
 }
diff --git a/tests/system/Database/Live/ModelTest.php b/tests/system/Database/Live/ModelTest.php
index 82ef23f36d78..ae4f5316cd5c 100644
--- a/tests/system/Database/Live/ModelTest.php
+++ b/tests/system/Database/Live/ModelTest.php
@@ -1367,6 +1367,17 @@ public function testPaginatePassPerPageParameter()
 
 	//--------------------------------------------------------------------
 
+	public function testPaginateForQueryWithGroupBy()
+	{
+		$model = new ValidModel($this->db);
+		$model->groupBy('id');
+
+		$model->paginate();
+		$this->assertEquals(4, $model->pager->getDetails()['total']);
+	}
+
+	//--------------------------------------------------------------------
+
 	public function testValidationByObject()
 	{
 		$model = new ValidModel($this->db);