Подтвердить что ты не робот

Как обратиться к одному CTE дважды?

У меня очень жирное общее табличное выражение, которое включает номера строк, так что я могу вернуть вычисленный набор результатов. Я также хочу вернуть общее количество записей, которые соответствуют запросу, прежде чем я нарисую результирующий набор.

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?

4b9b3361

Ответ 1

Вы можете использовать запятые для создания нескольких 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

Ответ 2

Не думай, что можешь. Из MSDN

Общее табличное выражение (CTE) может быть как временный результирующий набор который определяется в ходе выполнения масштаб одного SELECT, INSERT, ОБНОВЛЕНИЕ, УДАЛЕНИЕ или СОЗДАНИЕ ВИДОВ утверждение.

Акцент на "одиночный запрос SELECT, INSERT, UPDATE, DELETE или CREATE VIEW".

Это может быть ситуация, когда вы хотите использовать временную таблицу .

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 ......

Вы сможете использовать временную таблицу так, как вы описали выше.

Ответ 3

Вы можете добавить поле, содержащее в нем полные строки, конечно, оно будет в каждой строке

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

Ответ 4

Это лучшее:

;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

Ответ 5

Вот как мы имеем дело с поисковым вызовом (без управления сеансом на данный момент) в производственной среде. Выполняется, как ожидалось.

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