T-SQL динамический порядок в общей таблице для разбивки на страницы - PullRequest
4 голосов
/ 10 мая 2011

Я нашел отличный SQL-код для динамической сортировки и порядка, но мне интересно, может ли кто-нибудь помочь мне перенастроить его так, чтобы CTE в PROC ниже использовал динамическую сортировку / порядок.Этот код выполняется, но вывод не тот, что я получаю после того, как ORDER BY p.ProductId сначала выполняется в CTE, а затем оператор ORDER BY CASE применяется только к записям от 6 до 10

DECLARE @Skip int
DECLARE @Take int
DECLARE @OrderBy VARCHAR(50)

SET @Skip = 5;
SET @Take = 5;
SET @OrderBy = 'PriceAsc';


WITH ProductCT AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY p.ProductId) AS RowNum
    , p.ProductId
    FROM dbo.Product AS p
)
SELECT   p.ProductId
        ,p.Title
        ,p.Price
FROM dbo.Product AS p
INNER JOIN ProductCT AS pct ON pct.ProductId = p.ProductId
WHERE pct.RowNum BETWEEN @Skip + 1 AND (@Skip + @Take)
ORDER BY
    CASE     
         WHEN @OrderBy = 'TitleAsc' THEN (RANK() OVER (ORDER BY p.Title))
         WHEN @OrderBy = 'TitleDesc' THEN (RANK() OVER (ORDER BY p.Title DESC))
         WHEN @OrderBy = 'PriceAsc' THEN (RANK() OVER (ORDER BY p.Price))
         WHEN @OrderBy = 'PriceDesc' THEN (RANK() OVER (ORDER BY p.Price DESC))
         ELSE (RANK() OVER (ORDER BY p.Price))
    END

Спасибо взаранее за любые предложения: -)

Ответы [ 3 ]

10 голосов
/ 13 мая 2011

Я изначально пометил ответ @Johan как правильный, потому что он работал, но я был немного не уверен насчет ВНУТРЕННЕГО СОЕДИНЕНИЯ и общей сложности этого запроса.проблема, и он придумал это очень аккуратное решение (спасибо Том !!), поэтому я подумал, что поделюсь им:

DECLARE @Skip int
DECLARE @Take int
DECLARE @OrderBy VARCHAR(50)

SET @Skip = 5;
SET @Take = 5;
SET @OrderBy = 'PriceAsc';


WITH ProductCT AS
(
    SELECT
    CASE
       WHEN @OrderBy = 'TitleAsc' THEN ROW_NUMBER() OVER (ORDER BY p.Title)
       WHEN @OrderBy = 'TitleDesc' THEN ROW_NUMBER() OVER (ORDER BY p.Title DESC)
       WHEN @OrderBy = 'PriceAsc' THEN ROW_NUMBER() OVER (ORDER BY p.Price)
       WHEN @OrderBy = 'PriceDesc' THEN ROW_NUMBER() OVER (ORDER BY p.Price DESC)
    END AS RowNum
    , p.ProductId
    FROM dbo.Product AS p
)
SELECT   p.ProductId
        ,p.Title
        ,p.Price
FROM dbo.Product AS p
INNER JOIN ProductCT AS pct ON pct.ProductId = p.ProductId
WHERE pct.RowNum BETWEEN @Skip + 1 AND (@Skip + @Take)
ORDER BY RowNum
0 голосов
/ 15 марта 2012

Решения Роба у меня почему-то не работают, вот моя модифицированная версия, которая работала нормально.

       SELECT
          ROW_NUMBER() OVER (ORDER BY 
    CASE
       WHEN @sortOrder = 'TitleAsc' THEN p.Title
       WHEN @sortOrder = 'TitleDesc' THEN  p.Title
       WHEN @sortOrder = 'PatientId' THEN  p.Title
       WHEN @sortOrder = 'PriceAsc' THEN  p.Title
       WHEN @sortOrder = 'PriceDesc' THEN  p.Title
    END ASC) AS [RowNum],
       .................
      ..................
0 голосов
/ 10 мая 2011

Вот решение, которое должно работать.

WITH ProductCT AS
(
    SELECT  ROW_NUMBER() OVER(ORDER BY p.Title) AS RowNum1
            ,ROW_NUMBER() OVER(ORDER BY p.Title DESC) AS RowNum2
            ,ROW_NUMBER() OVER(ORDER BY p.Price) AS RowNum3
            ,ROW_NUMBER() OVER(ORDER BY p.Price DESC) AS RowNum4
            ,p.ProductId
    FROM dbo.Product AS p
)
SELECT   p.ProductId
        ,p.Title
        ,p.Price
FROM dbo.Product AS p
INNER JOIN ProductCT AS pct 
    ON  pct.ProductId = p.ProductId
    AND ((@OrderBy = 'TitleAsc' AND pct.RowNum1 BETWEEN @Skip + 1 AND (@Skip + @Take))
    OR  (@OrderBy = 'TitleDesc' AND pct.RowNum2 BETWEEN @Skip + 1 AND (@Skip + @Take))
    OR  (@OrderBy = 'PriceAsc' AND pct.RowNum3 BETWEEN @Skip + 1 AND (@Skip + @Take))
    OR  (@OrderBy = 'PriceDesc' AND pct.RowNum4 BETWEEN @Skip + 1 AND (@Skip + @Take))
    )
ORDER BY
    CASE @OrderBy
         WHEN 'TitleAsc' THEN RowNum1
         WHEN 'TitleDesc' THEN RowNum2
         WHEN 'PriceAsc' THEN RowNum3
         WHEN 'PriceDesc' THEN RowNum4
         ELSE RowNum3
    END

Я думаю, что JOIN можно написать лучше, но сейчас у меня нет больше времени.

...