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

发布于 2024-11-06 00:27:26 字数 1044 浏览 1 评论 0原文

我发现了一些很棒的动态排序和排序的sql代码。顺序,但我想知道是否有人可以帮助我重新调整它,以便下面的 PROC 中的 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

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

I found some great sql code for dynamic sort & order but I am wondering if someone can help me re-jig it so that the CTE in the PROC below uses the dynamic sort/order. This code runs - but the output is not what I am after as the ORDER BY p.ProductId happens first in the CTE then the ORDER BY CASE statement only applies to the records 6 to 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

Thanks in advance for any suggestions :-)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

黑凤梨 2024-11-13 00:27:26

我最初将 @Johan 的答案标记为正确,因为它有效,但我有点不确定 INNER JOIN 以及该查询的整体复杂性。

我和我的一位同事讨论了这个问题,他想出了这个非常简洁的解决方案(谢谢汤姆!)所以我想我会分享它:

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

I originally marked the answer from @Johan as correct because it worked, but I was a little unsure about the INNER JOIN also the overall complexity of this query.

I got chatting with a colleague of mine about the problem and he came up with this very tidy solution (thanks Tom!!) so I thought I would share it:

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
风透绣罗衣 2024-11-13 00:27:26

这是一个应该有效的解决方案。

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

Here is a solution that should work.

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

I think the JOIN could be written better but I dont have more time right now.

旧时光的容颜 2024-11-13 00:27:26

罗布的解决方案不知何故对我不起作用,这是我的修改版本,效果很好。

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

Rob's solutions somehow doesn't work for me, here is my modified version which worked fine.

       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],
       .................
      ..................
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文