ページング SQL Server 2005 の結果
-
08-06-2019 - |
質問
SQL Server 2005 で結果をページングするにはどうすればよいですか?
SQL Server 2000 でこれを試しましたが、これを行う信頼できる方法はありませんでした。SQL Server 2005 に組み込みメソッドがあるかどうか疑問に思っています。
ページングとは、たとえば、ユーザー名でユーザーをリストする場合、最初の 10 レコードのみを返し、次の 10 レコードなどを返すようにしたいということです。
助けていただければ幸いです。
解決
使用できます the Row_Number()
関数。次のように使用されます。
SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
そこから、次の結果セットが生成されます。 RowID
ページ間を移動するために使用できるフィールド。
SELECT *
FROM
( SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
) As RowResults
WHERE RowID Between 5 AND 10
等
他のヒント
1 つのステートメント (合計とページング) で取得しようとしている場合。SQL Server の Partition by 句 (ANSI SQL 用語のウィンドウ関数) のサポートを調べる必要がある場合があります。Oracle では、構文は row_number() を使用した上記の例とまったく同じですが、ページングで返された各行に含まれる行の合計数を取得するために、partition by 句も追加しました (合計行数は 1,262)。
SELECT rn, total_rows, x.OWNER, x.object_name, x.object_type
FROM (SELECT COUNT (*) OVER (PARTITION BY owner) AS TOTAL_ROWS,
ROW_NUMBER () OVER (ORDER BY 1) AS rn, uo.*
FROM all_objects uo
WHERE owner = 'CSEIS') x
WHERE rn BETWEEN 6 AND 10
where owner = 'CSEIS' があり、パーティション by が所有者にあることに注意してください。結果は次のようになります。
RN TOTAL_ROWS OWNER OBJECT_NAME OBJECT_TYPE
6 1262 CSEIS CG$BDS_MODIFICATION_TYPES TRIGGER
7 1262 CSEIS CG$AUS_MODIFICATION_TYPES TRIGGER
8 1262 CSEIS CG$BDR_MODIFICATION_TYPES TRIGGER
9 1262 CSEIS CG$ADS_MODIFICATION_TYPES TRIGGER
10 1262 CSEIS CG$BIS_LANGUAGES TRIGGER
これに対する受け入れられている答えは、実際には私にとっては機能しません...機能させるには、もう1つのフープを飛び越える必要がありました。
答えを試してみたところ
SELECT Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
WHERE RowID Between 0 AND 9
RowID が何であるかがわからないと不平を言って失敗しました。
次のように内部選択でラップする必要がありました。
SELECT *
FROM
(SELECT
Row_Number() OVER(ORDER BY UserName) As RowID, UserFirstName, UserLastName
FROM Users
) innerSelect
WHERE RowID Between 0 AND 9
そしてそれはうまくいきました。
ページングを行う必要がある場合、通常は一時テーブルも使用します。出力パラメータを使用して、レコードの合計数を返すことができます。select の case ステートメントを使用すると、動的 SQL に頼ることなく、特定の列のデータを並べ替えることができます。
--Declaration--
--Variables
@StartIndex INT,
@PageSize INT,
@SortColumn VARCHAR(50),
@SortDirection CHAR(3),
@Results INT OUTPUT
--Statements--
SELECT @Results = COUNT(ID) FROM Customers
WHERE FirstName LIKE '%a%'
SET @StartIndex = @StartIndex - 1 --Either do this here or in code, but be consistent
CREATE TABLE #Page(ROW INT IDENTITY(1,1) NOT NULL, id INT, sorting_1 SQL_VARIANT, sorting_2 SQL_VARIANT)
INSERT INTO #Page(ID, sorting_1, sorting_2)
SELECT TOP (@StartIndex + @PageSize)
ID,
CASE
WHEN @SortColumn='FirstName' AND @SortDirection='ASC' THEN CAST(FirstName AS SQL_VARIANT)
WHEN @SortColumn='LastName' AND @SortDirection='ASC' THEN CAST(LastName AS SQL_VARIANT)
ELSE NULL
END AS sort_1,
CASE
WHEN @SortColumn='FirstName' AND @SortDirection='DES' THEN CAST(FirstName AS SQL_VARIANT)
WHEN @SortColumn='LastName' AND @SortDirection='DES' THEN CAST(LastName AS SQL_VARIANT)
ELSE NULL
END AS sort_2
FROM (
SELECT
CustomerId AS ID,
FirstName,
LastName
FROM Customers
WHERE
FirstName LIKE '%a%'
) C
ORDER BY sort_1 ASC, sort_2 DESC, ID ASC;
SELECT
ID,
Customers.FirstName,
Customers.LastName
FROM #Page
INNER JOIN Customers ON
ID = Customers.CustomerId
WHERE ROW > @StartIndex AND ROW <= (@StartIndex + @PageSize)
ORDER BY ROW ASC
DROP TABLE #Page
これを無理なく実行するには、別のクエリを実行する必要があると思います。
私は以前の職でこのページの助けを借りてこれを達成することができました。DotNet 2.0 でのページング
また、行数を個別に取得することもできます。
ページングのために私が行うことは次のとおりです。ページングする必要がある大きなクエリはすべて、一時テーブルへの挿入としてコード化されています。一時テーブルには、前述の row_number() と同様の方法で動作する ID フィールドがあります。一時テーブルの行数を出力パラメータに保存することで、呼び出し元のコードが合計レコード数を認識できるようにします。呼び出しコードでは、必要なページと、一時テーブルから選択されるページごとの行数も指定します。
この方法の優れた点は、アプリケーションの各グリッド上に CSV として返されたレポートからすべての行を取得できる「エクスポート」リンクも用意されていることです。このリンクでは、同じストアド プロシージャを使用します。ページング ロジックを実行する代わりに、一時テーブルの内容を返すだけです。これにより、ページングを嫌うユーザーをなだめることができます。 すべて, 、それを何百万もの異なる方法で並べ替えたいと考えています。