web-dev-qa-db-ja.com

1つのCTEを2回参照する方法は?

ページングされた結果セットを返すことができるように、行番号を含む非常に太い共通テーブル式があります。また、結果セットをページングする前に、クエリに一致するレコードの総数を返したいと思います。

with recs as (select *, row_number() over (order by id) as rownum from ......)
select * from recs where rownum between @a and @b .... select count(*) from recs

明らかに上記の私のクエリはパッチがありますが、それは私のポイントを説明するためだけのものです。結果のページと一致の総数が必要です。 20行以上のCTE全体を文字通りコピーして貼り付けることなく、これを行うにはどうすればよいですか?

25
Nathan Ridley

カンマを使用して、上記のCTEを参照する複数のCTEを作成できます。

私が何を意味するかを説明するためだけに:

with recs as (
select 
    *, 
    row_number() over (order by id) as rownum from ......
    ),
counts as (
    select count(*) as totalrows from recs
)
select recs.*,count.totalrows
from recs
cross apply counts 
where rownum between @a and @b .... 

これは良い解決策ではありません。

レコードをカウントせずにCTEに合計カウントがあることがわかった最善の解決策は、 この記事 で説明されています。

DECLARE @startRow INT; SET @startrow = 50;
WITH cols
AS
(
    SELECT table_name, column_name, 
        ROW_NUMBER() OVER(ORDER BY table_name, column_name) AS seq, 
        ROW_NUMBER() OVER(ORDER BY table_name DESC, column_name desc) AS totrows
    FROM [INFORMATION_SCHEMA].columns
)
SELECT table_name, column_name, totrows + seq -1 as TotRows
FROM cols
WHERE seq BETWEEN @startRow AND @startRow + 49
ORDERBY seq
19
Jose Chama

できるとは思わないでください。から [〜#〜] msdn [〜#〜]

共通テーブル式(CTE)は、単一のSELECT、INSERT、UPDATE、DELETE、またはCREATEVIEWステートメントの実行スコープ内で定義される一時的な結果セットと考えることができます。

「単一のSELECT、INSERT、UPDATE、DELETE、またはCREATEVIEWステートメント」に重点を置いています。

これは、 一時テーブル を使用したい状況である可能性があります。

CREATE TABLE #Recs
{
  .....
}
INSERT INTO #Recs
select *, row_number() over (order by id) as rownum from ......

事前にテーブルの構造がわからない場合は、次のフォームを使用して一時テーブルを作成できます。

select *, row_number() over (order by id) as rownum INTO #Recs from ......

上記の方法で一時テーブルを使用できるようになります。

19
Abe Miessler

合計行を含むフィールドを追加できます。もちろん、すべての行にあります。

select recs.*,totalrows = (select count(0) from recs) 
from recs
4
jw56578

これが、実稼働環境でのページング(現時点ではセッション管理なし)の処理方法です。期待どおりに動作します。

DECLARE
   @p_PageNumberRequested  int = 1,
      -- Provide -1 to retreive all pages with all the rows.
   @p_RowsPerPage          int = 25

;WITH Numbered AS (
SELECT
   ROW_NUMBER() OVER (ORDER BY YourOrdering) AbsoluteRowNumber
,  COUNT(1) OVER () TotalRows
,  YourColumns
FROM
   YourTable
),
Paged AS (
SELECT
   (AbsoluteRowNumber - 1) / @p_RowsPerPage + 1 PageNumber,
   *
FROM
   Numbered)
SELECT
   ROW_NUMBER() OVER(PARTITION BY PageNumber ORDER BY AbsoluteRowNumber) RowNumberOnPage,
   *
FROM
   Paged
WHERE
      PageNumber = @p_PageNumberRequested
   OR
      @p_PageNumberRequested = -1
ORDER BY 
   AbsoluteRowNumber
1
Prof

これが一番:

;WITH recs AS
(SELECT a,b,c,
      row_number() over (
                         ORDER BY id) AS RowNum,
                   row_number() over () AS RecordCount
FROM ......)
SELECT a,b,c,rownum,RecordCount FROM recs
WHERE rownum BETWEEN @a AND @b
1
Hugo Valer