- PR -

データベースからある範囲のデータを取り出す方法について

投稿者投稿内容
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2004-02-17 19:52
永井和彦さん、返答ありがとうございます。
(一文字違いで自分の先輩の名前なのでドキッとしてしまったw)

引用:

永井和彦さんの書き込み (2004-02-17 17:57) より:

このユーザー要求はとりあえず関係無いですよね?内側のTOP句に使う数字は常に総件数とページ数に引っ張られて変化しますし。

#途中で主旨から離れて迷走していたため、後半部分を削除しました。

[ メッセージ編集済み 編集者: 永井和彦 編集日時 2004-02-17 18:19 ]



うわ、よく考えたらそうでした。。。ユーザー要求とは関係なくTOP句に指定する数値は動的になりますね。ボケてます。。。(悲

# 最初の書き込みを参照した後、打合せになってしまっため返答が遅れましたが、
# エレガントさうんぬんの話は興味のある話ではあり、
# 文字列結合も致し方ないと思うのですが、保守性の面において問題ありと
# 認識している部分があるからです。まあ、この話は置いておきましょう。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-17 19:53
引用:

noderaさんの書き込み (2004-02-17 18:03) より:

また、ソート順を使ったクエリの結果から特定のページを取り出すにはrownumを使用するときにちょっとした裏技(う、ウラワザなんだ)を使う必要があるようです。


 ROWNUMが振られるのはORDER BYよりも前なので、ソートした結果ではないのです。そのためにインラインビューを使うのですが、それが「裏技」なんですね。。。

 「全体のn%を返す」というのはあるんですけどね。。。
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2004-02-17 21:39
引用:

きくちゃんさんの書き込み (2004-02-17 18:28) より:

プロシージャの代わりに TABLE 型を返すユーザ定義関数を使用して、
SELECT TOP n .... FROM MY_FUNCTION(....)
というようなSQLを組み立てて発行すれば良いような気がしますが、如何でしょうか。




きくちゃんさん、返答ありがとうございます。
ユーザー定義関数については使用したことがなかったのと、「文字列結合を使用せずにTOP句に指定する数値を可変にしたい、またはそれに類する構文の書き方があれば知りたい」という要求に対する直接的な回答ではないような気がしましたので、自分なりにユーザー定義関数について調べていました。
しかしながら、こうすればできる!というような解にたどり着くことが出来ませんでした。
(こうやってもできなかったという以前に、こうすればもしかしてという考えにもたどり着けませんでした、とほほ)

申し訳ありませんが、具体的な方法等を示していただけると助かります。
(そこまで甘えるのもなんなんですが・・・)
きくちゃん
ぬし
会議室デビュー日: 2003/08/01
投稿数: 854
お住まい・勤務地: 都内某所
投稿日時: 2004-02-18 02:59
noderaさん、こんばんは。

引用:

申し訳ありませんが、具体的な方法等を示していただけると助かります。



以下は、与えられたパラメータを抽出条件としてクエリを実行し、その結果セットを取得する単純なテーブル値関数のサンプルです。

コード:
CREATE FUNCTION MY_FUNCTION(@PARAM1 INT) 
    RETURNS @RESULTS TABLE(FIELD1 INT, FIELD2 VARCHAR(10)) AS
BEGIN
    INSERT INTO @RESULTS
    SELECT FIELD1, FIELD2
    FROM HOGEHOGE
    WHERE FIELD3 = @PARAM1

    RETURN
END


この関数の実行結果から先頭の10行を取得する場合、
SELECT TOP 10 FIELD1, FIELD2 FROM MY_FUNCTION(10)
というようなSQLを発行しますが、この程度のSQLなら文字列操作で組み立てても、「コンパイル済みクエリの利点を活かしつつ、なおかつ TOP n も動的に指定したい」という要求は満たせるのではないかと思います。

また、戻りや関数内で使用するTABLE型の変数を宣言する際、ID列の指定も可能(だったはず)ですので、ORACLEのROWNUMのような使い方も出来ると思います。
nodera
大ベテラン
会議室デビュー日: 2003/09/08
投稿数: 200
投稿日時: 2004-02-18 11:20
きくちゃんさん、返答ありがとうございます。

きくちゃんさん、Jittaさんの回答を再度検討し、そして結果を得ることに成功しました。
以下のサンプルで目的とするページを抽出できました。

----------------------------------------------------
ユーザー定義関数を使用して目的とするページのデータを取得する方法
----------------------------------------------------

ストアドプロシージャ側
CREATE PROCEDURE SP_HOGEHOGE
@pageLine int, -- 1ページあたりの行数
@page int -- 抽出対象ページ
as

-- 抽出開始行の計算
declare @startLine int
set @startLine = (@pageLine * (@page - 1)) + 1

-- 抽出終了行の計算
declare @endLine int
set @endLine = @startLine + @pageLine - 1

select HOGE_CODE1, HOGE_CODE2, HOGE_NAME from UserFunc() where rownum between @startLine and @endLine


----------------------------------------------------
ユーザー関数側

CREATE FUNCTION UserFunc()
RETURNS @Result TABLE(rownum int NOT NULL IDENTITY (1, 1), HOGE_CODE1 int, HOGE_CODE2 int, HOGE_NAME varchar(64)) AS
BEGIN
insert into @Result
(HOGE_CODE1, HOGE_CODE2, HOGE_NAME)
select
HOGE_CODE1,
HOGE_CODE2,
HOGE_NAME
from
HOGEHOGE_TABLE
order by
HOGE_CODE2,
HOGE_CODE1

-- テストのためあえてソートはCODE2、CODE1の順番
return
END

----------------------------------------------------
いやあ、なんだか喉のつかえが取れた気分ですよ!
これならTOP句も必要ないですね。

永井さんの返答にもちょこっと書きましたが、文字列結合でSQLを組み立てているとデバッグするのがかなり大変だということが分かります。自分の作ったものならまだしも、人の作ったものの不具合修正で、文字列結合だらけのSQLを面倒みなければならなくなった日には、あいたたたた。

まだユーザー定義関数自体についてと、ユーザー定義関数の中でInsertしている部分はパフォーマンスにどのくらい影響度があるのか等、調査は引き続き必要ですが、なにはともあれひとつの結果にたどり着くことができて、非常に勉強になりました。

返答してくださった皆さん、ありがとうございました。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2004-02-18 15:27
引用:

noderaさんの書き込み (2004-02-18 11:20) より:

文字列結合でSQLを組み立てているとデバッグするのがかなり大変だということが分かります。自分の作ったものならまだしも、人の作ったものの不具合修正で、文字列結合だらけのSQLを面倒みなければならなくなった日には、あいたたたた。


 確かに痛いです。また、私の方は現在Oracle、将来MSDEなので、2つの間でSQL文が違うのがなんとも。単純なSELECT以外はストアドプロシージャやビューを作って、コード中ではシンプルなSQLのみ記述するほうがいいなぁ、と、今痛感しています。痛い痛い。。。

スキルアップ/キャリアアップ(JOB@IT)