Как обратиться к одному 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?
Ответы
Ответ 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