MySQLでオートインクリメントを使用せずにグループ毎に連番を設定する方法
2025/06/19
MySQLでオートインクリメントを使用せずにグループ毎で連番を割り振りたかった。具体的には掲示板を作成する案件がありスレッド毎にレスナンバーを表示させたかった。以下にSQL文とPHPから実行させる方法をメモ。
MySQL8系以降は別の方法が便利(2025/06/19追記)
MySQLのバージョンが8系以降の場合は以下の方法を用いる方が楽で便利。
SQL文
phpmyadminやadminerからは以下SQL文でgroup_idごとに連番(no)が割り振られる。
SET @no:=0;
SET @group_id:=null;
SELECT
*,
IF(@group_id <> group_id, @no:=1, @no:=@no+1) AS no,
@group_id := group_id
FROM test_table
ORDER BY group_id DESC;
PHPからSQL文を発行する場合は以下になる。
$sql = 'SET @no:=0;';
$row = $mysqli->query($sql);
$sql = 'SET @group_id:=null;';
$row = $mysqli->query($sql);
$sql = '
SELECT
*,
IF(@group_id <> group_id, @no:=1, @no:=@no+1) AS no,
@group_id := group_id
FROM test_table
ORDER BY group_id DESC
;
ページングにも対応させたい
掲示板だと数十件ほどの書き込みごとに「次のページへ」等のページングが必要になるが、先述のソースだとページが切り替わるごとに上からレスナンバーが1~とリセットされてしまう。
そのような場合は以下のように変更することでページが切り替わってもレスナンバーが正常に表示されるようになる。
$page = 1; //ページ数 $limit = 20; //1ページの最大表示数 $offset = $page * $limit; $sql = 'SET @no:=' . $offset . ';';
アットマークとかコロンとかは何?
今回作成したSQL文は参考サイトを元にしたが、アットマークとかコロンなど平素では使用しない記述が多数見受けられた。
@(アットマーク)
変数を利用する際に使用する。PHPでいう$マークみたいなものっぽい。
:=(コロン・イコール)
イコールと同じ、もしくは代入の際に使用する。例えば以下だとnoという変数に0を代入するという意味になる。
$sql = 'SET @no:=0;';
IF(@group_id <> group_id, @no:=1, @no:=@no+1) AS noの部分
IF~からASまでの部分は参考演算子とのこと。group_idが等しくない場合はnoは1、同じ場合は+1とする。つまり同じグループであればインクリメントしていくといったもの。その値をnoカラムとして受け取られる(AS no部分)。
参考サイト
関連記事
-
-
Podmanで導入したデータベース(MariaDB)用コンテナのチューニングに関する設定方法
先日Podmanでデータベース(MariaDB)用コンテナを導入したが、当該コン ...
-
-
MySQLで1対多というテーブル構造でデータ結合と条件検索する方法
MySQLで飲食店舗テーブルと休業日テーブルがあり、1店舗に対して複数行の休業日 ...
-
-
MySQLとPHPの「image-comparator」ライブラリを使用して類似画像検索を実装する方法
先日PHPで画像を比較して類似度を算出する「image-comparator」ラ ...
-
-
WordPressでデータベース接続確立エラー発生時の対応方法
WordPressで「データベース接続確立エラー」というエラー表示がされた。大抵 ...
-
-
MySQLで「doesn't have a default value」エラーの対処
MySQLでINSERT時に「Field 'カラム名' doesn't have ...