質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

5083閲覧

MySQLで連番をINSERTと同時に挿入する方法

ikatako

総合スコア270

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

2クリップ

投稿2020/11/03 17:58

編集2020/11/03 22:20

###実現したいこと
レコードのINSERT時に、「グループごとのカラムの最大値+1」を自動で入れたいのですが、そんな都合のいい方法ございますか?

###テーブル構成
以下はコメントのテーブルで、order_numberでコメントの並び順が指定されています。
尚、order_numberはユーザーが任意に変更できるようになっています。

SQL

1CREATE TABLE p_comments 2 (`ID` int, `thread_ID` int, `order_number` int) 3; 4 5INSERT INTO p_comments 6 (`ID`, `thread_ID`, `order_number`) 7VALUES 8 (100, 11, 1), 9 (101, 12, 1), 10 (102, 13, 1), 11 (103, 11, 2), 12 (104, 13, 2), 13 (105, 12, 2), # thread_ID = 12 の最大 14 (106, 11, 3), 15 (107, 13, 3), # thread_ID = 13 の最大 16 (108, 11, 4) # thread_ID = 11 の最大 17;

例えばスレッドthread_ID = 12にコメントすると以下実行しますが、このとき同一スレッドにおけるorder_numberを自動で最大としてorder_number = 3を入れたいということです。
(現状のthread_ID = 12の最大のorder_number2であるためです。)

SQL

1INSERT INTO p_comments 2 (`ID`, `thread_ID`, `order_number`) 3VALUES 4 (109, 12, 3) 5;

###試している方法
クエリを2回発行すれば、目的は達成できることがわかりました。
つまりまず1回目に以下を実行して最大のorder_numerである2を得ます。
続いてPHPでその2に+1して、2回目のクエリで上記を実行するという方法です。
ですがこの2回のクエリにやや冗長さを覚えましたために、もし1回で済ませることができればと思い質問させて頂きました。

SQL

1SELECT `order_number` 2FROM `p_comments` 3WHERE thread_ID = 12 4ORDER BY `order_number` 5DESC LIMIT 1;

また、検索しますと以下リンクを見つけまして、

[MySQL] 連番をINSERTと同時に挿入する方法

https://b.0218.jp/20121112133354.html

この方法に従って次のSQLを実行したのですが、実現には至りませんでした。

SQL

1INSERT INTO p_comments( `order_number`, `ID`, `thread_ID` ) 2SELECT COALESCE(MAX(`order_number`)+1,1), ?, ? 3FROM p_comments;

###発生している問題
上記「実現には至りませんでした」について詳細補足します。

エラーはないのですが、order_numberが想定より大きな数字になってしまいます。

例えば現状でthread_ID = 12には2件のレコードがあったとして、order_numberは最大2ということですが、そこに上記実行しますとorder_number227が入るといった感じです。

この227が何の数字なのかわかりません。p_commentsテーブルのレコードは2121件ですし、思い当たるフシがないです。

さらにその上でもう一度実行すると228が入りこれは227の次なので正常ですが、そもそも227でなく3を入れたかったので困っています。

###バージョン
MySQLは5.7ですが、もし上位のバージョンでのみ可能であればアップデートも視野に入れています。
宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/11/03 18:16

「実現には至りませんでした。」とありますが、具体的にどのような状況になりました? エラーが出るなら、そのエラーの内容を書いてください。
ikatako

2020/11/03 19:19

失礼いたしました。エラーはないのですが、order_numberが想定より大きな数字になってしまいます。その旨「発生している問題」へ追記いたしましたので、ご確認頂けましたら幸いです。
CHERRY

2020/11/03 22:43 編集

試したことのSQLでは、select 文に条件をつけずに order_number を MAX しているので、どこかのthread_IDに 226 が存在しているから 227 になるとおもいます。 select 文を thread_ID で絞り込むとどうなりますか?
ikatako

2020/11/04 06:07

すみません、コメントに今気づきました。 > どこかのthread_IDに 226 が存在している とのことで以下実行しましたが、結果は0件でした。 SELECT * FROM `p_comments` WHERE `thread_ID` = 226
Yith

2020/11/20 07:46

質問に書かれているSQLは > SELECT COALESCE(MAX(`order_number`)+1,1), ?, ? なので、これだとorder_numberの最大値+1を取得してますが、ikatakoさんの返答にあるクエリ > SELECT * FROM `p_comments` WHERE `thread_ID` = 226 だと、thread_IDが226のレコードを取得しようとしてます。 226の数字を出どころを求めるなら、 SELECT * FROM p_comments WHERE order_number = 226 では?
guest

回答2

0

ベストアンサー

こうでしょうか。

SQL

1insert into p_comments 2 (`ID`, `thread_ID`, `order_number`) 3select null, 12, ifnull( 4 (select max(`order_number`) + 1 from p_comments where thread_ID = 12), 1 5);

IDにはAUTO_INCREMENTが指定されていて、
thread_IDをアプリケーションからバインドする場合
の想定です。

投稿2020/11/20 09:14

clickmaker

総合スコア200

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikatako

2021/01/17 23:15

どうもありがとうございます。おかげ様で楽に実装できました。 ちなみに次の結果によれば、IDにAUTO_INCREMENTがなくても、アプリケーションからバインドすれば(26行目で109を指定すれば)できるみたいです。 http://sqlfiddle.com/#!9/a23474/1
guest

0

functionで処理すれば不可能ではないですが、抜け番が出たりすると
結局番号のフリ直しが必要になったりするので、
逐次ランク処理をするのが賢明です

投稿2020/11/04 01:41

yambejp

総合スコア115010

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ikatako

2020/11/04 01:53

いつもありがとうございます。検索しているうちにyambejp様のご回答を見つけました。 https://teratail.com/questions/161776 これを参考に以下を書きましたら実現出来たようで今喜んでいるところなのですが、以下ですと何か不安が残りますでしょうか。たとえばどこかの値が保証されなかったりなど? ``` $ID = 109; $thread_id = 12; $sql = " INSERT INTO p_comments( ID, thread_ID, order_number ) SELECT * FROM( SELECT {$ID}, {$thread_id}, COALESCE(( # 初めてに備えて COALESCE を使う SELECT order_number +1 FROM p_comments AS comments1 # テーブルロックで複数の同名が使えないためエイリアス付与 WHERE thread_ID = {$thread_id} ORDER BY order_number DESC LIMIT 1 ),1) # AS order_number FROM p_comments AS comments2 # 同じくエイリアス付与 ) AS sub ON DUPLICATE KEY UPDATE order_number = VALUES(order_number) "; ```
yambejp

2020/11/04 02:16 編集

/* functionを使ったサンプル */ drop function if exists next_number; delimiter // create function next_number(thread int) RETURNS int DETERMINISTIC begin select coalesce(max(order_number),0)+1 into @a from p_comments where p_comments.thread_ID=thread; return @a; end // delimiter ;
yambejp

2020/11/04 02:16

/* insert処理 */ INSERT INTO p_comments (`ID`, `thread_ID`, `order_number`) VALUES (100,@a:=11,next_number(@a)), (101,@a:=12,next_number(@a)), (102,@a:=13,next_number(@a)), (103,@a:=11,next_number(@a)), (104,@a:=13,next_number(@a)), (105,@a:=12,next_number(@a)), (106,@a:=11,next_number(@a)), (107,@a:=13,next_number(@a)), (108,@a:=11,next_number(@a)); ;
yambejp

2020/11/04 02:17

この変数の使い方は保証外なので、ちゃんとやるなら変数ではなく 実数を入れる必要があります
ikatako

2021/01/17 23:46

あ、わかりました。2020/11/04 10:53 に記載いたしましたコードでは、レコードが0件のときにinsertされないというわけですね。いまTRUNCATE TABLEをしてそのことに気が付きました。どうもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問