6

使用 Microsoft SQL 服务器管理器 2008。

制作一个“最终”选择 Pareto 列表中前 10 个的存储过程。但我也想再次运行它以找到倒数 10。

现在,我没有重新复制查询,而是尝试查看是否有一种方法可以将参数传递到查询中,从而将顺序从 asc 更改为 desc。

有什么方法可以让我免于复制代码吗?

CREATE PROCEDURE [dbo].[TopVRM]
@orderby varchar(255)
AS
SELECT Peroid1.Pareto FROM dbo.Peroid1
GROUP by Pareto ORDER by Pareto @orderby
4

4 回答 4

10

只是有点傻:

CREATE PROCEDURE [dbo].[TopVRM]
@orderby varchar(255)
AS
SELECT Peroid1.Pareto FROM dbo.Peroid1
GROUP by Pareto
ORDER by CASE WHEN @orderby='ASC' THEN Pareto END,
         CASE WHEN @orderby='DESC' THEN Pareto END DESC

您根本不需要将第二个排序条件放在CASE表达式中(*),如果Pareto是数字,您可以决定只做CASE WHEN @orderby='ASC' THEN 1 ELSE -1 END * Pareto

(*) 只有当第一个排序条件认为两行相等时,第二个排序条件才有效。这是当两行具有相同的Pareto值时(因此反向排序也会认为它们相等),或者因为第一个CASE表达式返回NULLs (所以@orderbyis not 'ASC',所以我们想要执行DESC排序。


您可能还想考虑一次检索两个结果集,而不是进行两次调用:

CREATE PROCEDURE [dbo].[TopVRM]
@orderby varchar(255)
AS

SELECT * FROM (
    SELECT
       *,
       ROW_NUMBER() OVER (ORDER BY Pareto) as rn1,
       ROW_NUMBER() OVER (ORDER BY Pareto DESC) as rn2
    FROM (
        SELECT Peroid1.Pareto
        FROM dbo.Peroid1
        GROUP by Pareto
    ) t
) t2
WHERE rn1 between 1 and 10 or rn2 between 1 and 10
ORDER BY rn1

这将为您提供前 10 名和后 10 名,按从上到下的顺序排列。但是,如果总共少于 20 个结果,您将不会得到重复,这与您当前的计划不同。

于 2012-09-13T13:22:03.343 回答
1

尝试:

 CREATE PROCEDURE [dbo].[TopVRM]
(@orderby varchar(255)
AS
IF @orderby='asc'
SELECT Peroid1.Pareto FROM dbo.Peroid1
GROUP by Pareto ORDER by Pareto asc
ELSE
SELECT Peroid1.Pareto FROM dbo.Peroid1
GROUP by Pareto ORDER by Pareto desc
于 2012-09-13T13:21:47.057 回答
0

我知道它已经很老了,但只是想在这里分享我们的解决方案,希望对某人有所帮助:)

在对几个候选解决方案进行了一些性能测试(其中一些发布在这个线程中)之后,我们意识到你必须非常小心你的实现:你的 SP性能可能会受到巨大影响,特别是当你将它与分页问题结合起来时。

我们找到的最佳解决方案是保存原始结果,即。只需在时态表中应用过滤器(#RawResult在示例中),然后添加ORDER BYandOFFSET子句进行分页。也许这不是最漂亮的解决方案(因为您被迫为要排序的每一列复制和粘贴一个子句两次),但在性能方面我们无法找到其他更好的解决方案。

它是这样的:

CREATE PROCEDURE [dbo].[MySP]
    -- Here goes your procedure arguments to filter results
    @Page INT = 1,                  -- Resulting page for pagination, starting in 1
    @Limit INT = 100,               -- Result page size
    @OrderBy NVARCHAR(MAX) = NULL,  -- OrderBy column
    @OrderByAsc BIT = 1             -- OrderBy direction (ASC/DESC)
AS

-- Here goes your SP logic (if any)

SELECT 
    * -- Here goes your resulting columns
INTO
    #RawResult
FROM 
    ...
-- Here goes your query data source([FROM], [WHERE], [GROUP BY], etc)
-- NO [ORDER BY] / [TOP] / [FETCH HERE]!!!!

--From here, ORDER BY columns must be copy&pasted twice: ASC and DESC orders for each colum
IF (@OrderByAsc = 1 AND @OrderBy = 'Column1')
    SELECT * FROM #RawResult ORDER BY Column1 ASC OFFSET @Limit * (@Page - 1) ROWS FETCH NEXT @Limit ROWS ONLY
ELSE
IF (@OrderByAsc = 0 AND @OrderBy = 'Column1')
    SELECT * FROM #RawResult ORDER BY Column1 DESC OFFSET @Limit * (@Page - 1) ROWS FETCH NEXT @Limit ROWS ONLY
ELSE
IF (@OrderByAsc = 1 AND @OrderBy = 'Column2')
    SELECT * FROM #RawResult ORDER BY Column2 ASC OFFSET @Limit * (@Page - 1) ROWS FETCH NEXT @Limit ROWS ONLY
ELSE
IF (@OrderByAsc = 0 AND @OrderBy = 'Column2')
    SELECT * FROM #RawResult ORDER BY Column2 DESC OFFSET @Limit * (@Page - 1) ROWS FETCH NEXT @Limit ROWS ONLY
ELSE
    ...
ELSE --Default order, first column ASC
    SELECT * FROM #RawResult ORDER BY 1 ASC OFFSET @Limit * (@Page - 1) ROWS FETCH NEXT @Limit ROWS ONLY

于 2021-03-16T16:12:37.817 回答
0

这为您提供了更多选择

CREATE PROCEDURE [dbo].[TopVRM] @orderby varchar(255) = 'Pareto asc'
DECLARE @SendIt NVARCHAR(MAX)
AS
BEGIN
    SET @SendIt = 'SELECT Peroid1.Pareto FROM dbo.Peroid1
                   GROUP by Pareto ORDER by '+ @orderby
    EXEC sp_executesql @SendIt
END
GO
EXEC dbo.TopVRM 'Pareto DESC'
GO
于 2021-12-16T10:25:28.630 回答