Laravelのdistinct()とcount()を一緒に使うときは気をつける

Laravelのdistinct()とcount()を一緒に使っていて、ハマったので、自分のメモとしてまとめておきます。

以下のような構造のテーブルがあるとします。

CREATE TABLE `threads` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`project_id` int(10) UNSIGNED NOT NULL,
`title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

このテーブルからユニークなproject_idを取得する場合、以下のような感じのスクリプトになります。これは期待通りに動きます。

DB::table('threads')
->select('project_id')
->distinct()
->get();

ちなみにSQLを確認してみると以下のようになっています。

select distinct `project_id` from `threads`

次にユニークなproject_idの個数を取得する場合、get()のかわりにcount()を使えばよいかと安易に考えて、以下のような感じのスクリプトを書くと困った事になります。

DB::table('threads')
->select('project_id')
->distinct()
->count();

SQLとしては、以下のような感じになっているので、project_idは関係なく、threadsテーブルに含まれるデータ数を取得してます。

select count(*) as aggregate from `threads`

distinct()とcount()を一緒に使う場合は、以下のようなスクリプトにすると期待通りの結果を得ることができます。

DB::table('threads')
->distinct('project_id')
->count('project_id');

なお、SQLは以下のようになっています。

select count(distinct `project_id`) as aggregate from `threads`