Tsql 用于分页的公共表中的T-SQL动态Order By

Tsql 用于分页的公共表中的T-SQL动态Order By,tsql,pagination,dynamic-sql,common-table-expression,Tsql,Pagination,Dynamic Sql,Common Table Expression,我发现了一些关于动态排序和顺序的很棒的sql代码,但是我想知道是否有人可以帮助我重新调整它,以便下面的过程中的CTE使用动态排序/顺序。这段代码运行-但输出不是我想要的,因为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 @Orde

我发现了一些关于动态排序和顺序的很棒的sql代码,但是我想知道是否有人可以帮助我重新调整它,以便下面的过程中的CTE使用动态排序/顺序。这段代码运行-但输出不是我想要的,因为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

提前感谢您的任何建议:-)

这里有一个解决方案应该是可行的

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
可以写得更好,但我现在没有更多的时间。

我最初将@Johan的答案标记为正确,因为它有效,但我对内部连接以及此查询的整体复杂性有点不确定

我与我的一位同事就这个问题进行了交谈,他提出了一个非常简洁的解决方案(谢谢Tom!!),因此我想我会与大家分享:

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

Rob的解决方案不知何故对我不起作用,这是我的改进版,效果很好

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

为什么要在“排序依据”中使用
RANK()
?因为这是我能找到的唯一允许您将ASC/DESC添加到CASE语句中的方法。我在谷歌上找到了代码,它可以工作-如果有更好的方法,请告诉我:-)很好。比我的好多了。你让我们走上了正确的道路,约翰-谢谢你的帮助:-)没问题。顺便说一句,我现在注意到您的
行号()
都在使用
p.Title
。可能是打字错误……:)感谢我已经修复了它们-被复制粘贴怪兽捕获:-)我发现唯一有效的解决方案是不使用动态SQL,但有趣的是,它不起作用,我已经在生产环境中运行了几个月了,效果不错。