- - PR -
SQLについて
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2009-03-04 17:09
要件について、もう一度確認したいのですが。
次のようにしたいのでは? ケース1 未採番の場合・・・nullで返るので、1(最小値)とする ケース2 n番まで採番されており、空き番号がない場合・・・n+1とする ケース3 n番まで採番されており、空き番号がある場合・・・空きのうち、最小値 ケース3で、例えば1〜3、7〜10が空きになっていた場合、採用された方法では、1ではなく7が返されます。 それでokなのでしょうか? | ||||
|
投稿日時: 2009-03-04 22:53
これでいいでしょう
参考リンク 分析関数の衝撃5(総集編) http://codezine.jp/article/detail/1594 | ||||
|
投稿日時: 2009-03-05 08:36
忠犬様、明智重蔵様回答ありがとうございます。
忠犬様ご指摘ありがとうございます。 >ケース3で、例えば1〜3、7〜10が空きになっていた場合、採用された方法では、1ではなく7が返されます。 OKではないです。失礼いたしました。 明智重蔵様 参考サイト拝見させていただきました。 動作も確認取れましたありがとうございました。 皆様に教えていただいた方法を試して、速度を計測してみたいと思います。 計測いたしましたら、またご報告申し上げます。 | ||||
|
投稿日時: 2009-03-05 16:25
お疲れ様です。
SQLの計測を行った結果をご報告いたします。 テスト環境は4998件のレコードを準備 歯抜けは2991,3980です。 VB.NETのfor-next構文で1000回実行した時の実行時間を計測します。 それぞれ5回実行し中間時間をサンプリングする。 今回測定したのは、 NO1. 【SQL】連番の歯抜けの検索の改良型として、 忠犬様に提示していただいたSQL select min(seq+1) as gap from (select seq from seqtbl union select 0 as seq from seqtbl) as x where (seq+1) not in(select seq from seqtbl) NO2. 明智重蔵様のSQL select coalesce(max(seq), 0) + 1 as gap from (select seq, Row_Number() over(order by seq) as Rank from SeqTbl) d where seq = Rank; NO3. 私の作成したNULLをストアドのIF文でチェックするSQL ALTER PROCEDURE [dbo].[Get_Insert_Key] @keyvalue integer OUTPUT AS BEGIN SET NOCOUNT ON; SELECT @keyvalue = MIN(key + 1) FROM Table_A WHERE (key + 1) NOT IN ( SELECT key FROM Table_A); IF @keyvalue IS NULL BEGIN SET @keyvalue = 1 END END 以上を測定いたしました。 TEST1 プログラム中にコンスタント値としてNO1.のSQLを持ちExecuteScalarを実行した場合。 00:00:05.8254892 が中間的な速度でした。 TEST2 NO1.のSQLをストアドに登録し、ExecuteScalarを実行した場合。 00:00:05.8229156 が中間的な速度でした。 TEST3 NO1.のSQLをストアドに登録し、OUTPUTを作成、ExecuteNonQueryを実行しOUTPUTを取得する場合。 00:00:05.8401467 が中間的な速度でした。 TEST4 NO2.のSQLをストアドに登録し、ExecuteScalarを実行した場合。 00:00:02.3820686 が中間的な速度でした。 TEST5 NO2.のSQLをストアドに登録し、OUTPUTを作成、ExecuteNonQueryを実行しOUTPUTを取得する場合。 00:00:02.3951854 が中間的な速度でした。 TEST6 NO3.のSQLをストアドに登録し、OUTPUTを作成、ExecuteNonQueryを実行しOUTPUTを取得する場合。 00:00:07.0363274 が中間的な速度でした。 以上です。 1.ストアドもプログラムからのSQL発行もほぼ速度的な違いはありませんでした。 2.ストアドの実行方法は、OUTPUTパラメータを準備するため、ExecuteNonQueryを実行しOUTPUTを取得の方法は遅くなる。 3.ストアド中の判定文は遅い。 4.集計関数は非常に早い。 | ||||
|
投稿日時: 2009-03-05 18:01
いまさらですが。。
パラメータを利用しないで、こんな感じでINSERT文などにそのまま組み込めるということでした。 INSERT INTO tbl ( key , a , b , c ) VALUES ( dbo.GetKey() , 'aaa' , 'bbb' , 'ccc' ) 中のGetKey()で難しいことを行っても、外側はシンプルになります。 | ||||
|
投稿日時: 2009-03-05 23:25
「採番」列に、インデクスを適切に定義しているでしょうか?
母体データが数千件なのに、数秒かかるというのは、テーブルスキャンが発生しているように感じます。 特に、「SQL Server 2005」とのことのようなので、Oracleでいう「分析関数」を使用した場合、インデクスのアクセスのみで結果を得られるはずなのですけどね。 | ||||
|
投稿日時: 2009-03-06 09:06
おはようございます。
よっしー様、忠犬様回答ありがとうございます。 よっしー様 EXECUTEを使用しなくてもストアドを実行できるということですよね、知りませんでした。 1項目の戻り値であればとても有効ですね、勉強になりましたありがとうございます。 忠犬様 インデックスは使用しています。 母体データが数千件ですが、1000回実行だとしても遅いのでしょうか? For i As Integer = 1 To 1000 Try Using cmd As SqlCommand = New SqlCommand cmd.CommandType = CommandType.StoredProcedure cmd.CommandText = "test3" cmd.Connection = cn key = cmd.ExecuteScalar() 'Console.WriteLine(key.ToString) End Using Catch ex As Exception End Try Next 実際のロジックです。 | ||||
|
投稿日時: 2009-03-06 10:46
失礼、完全に見落としていました。 |