僕は「博多弁でいこう!」というサイトを運用しています。
このサイトは、もう25年くらい前にPerlのcgiで作ったのが最初で、その後、PHPへ移植。
さらに、CakePHP3化し、現在はCakePHP4で運用しています。CakePHP化したのは、勉強のためという意味合いが強いのですが。
このサイトには、掲載している言葉(博多弁)を使っていたかどうかのアンケートがあります。アンケートの内容は、使っていたかどうかの選択と、回答者の生年と性別、それとフリーのコメントからなります。
各言葉はテーブル(words)に、アンケート結果はテーブル(votes)に保存しています。
テーブル(words)は、テーブル(votes)をHasManyしています。
投票結果のページでは、使っていたかどうかの回答について、回答者の生年から算出した年代と性別でグループ分けして、それぞれの人数を表示するようにしています。
https://sunnyday-aki.ssl-lolipop.jp/hakataben/votes/result
それぞれの言葉の投票結果を一気に取得するために、caseステートメントを使用しました。
世代絞り込みのcaseは以下のような感じです。
カラムyesnoは、1で使っていた。0は使っていなかった。
birthyearは生年。西暦の数値です。sexは性別。
$q1 = $query->newExpr()->case() ->when( $query->newExpr()->add( [ 'yesno' => 1, $query->newExpr()->between('birthyear', '40才の生年', '21才の生年' ), ] ) ) ->then( 1 )->else(0);
上記は、21〜40才で使っていた人を絞り込むcase。
$q2 = $query->newExpr()->case() ->when( $query->newExpr()->add( [ 'yesno' => 0, 'sex' => 1, $query->newExpr()->between('birthyear', '60才の生年', '41才の生年' ), ] ) ) ->then( 1 )->else(0);
上記は、41〜60才の男性で使っていなかった人を絞り込むcase。
whenの条件にマッチすると1が、マッチしなければ0が返ってきます。
これらを以下のようにsumで集計すれば、それぞれの言葉の世代別、回答別の人数を算出できます。
$query->select([ 'age20_yes' => $query->func()->sum($q1), 'age60_m_no' => $query->func()->sum($q2), ]);
実際に生成されたSQL文をdebug.kitで確認すると、以下のようになっています。
SUM( CASE WHEN ( yesno = 0 AND sex = 1 AND birthyear BETWEEN 1983 AND 2002 ) THEN 1 ELSE 0 END )
※現在、絶賛お仕事募集中です。興味をお持ちのかたは、以下の問い合わせフォームから
https://www.fourthgate.jp/index.php/contact/
から、是非是非ご連絡ください。