具有多列和不同排序选项的 CASE ORDER BY

Eri*_*eid 6 stored-procedures order-by t-sql case

我试图CASE ORDER BY在存储过程中使用 T-SQL,在其中我将 @OrderBy 参数作为 TINYINT 传递。

  • @Orderby = 1 Then Date column should be ASC
  • @Orderby = 2 Then Date column should be DESC

我的问题是:当我为该参数传递 2 时,如何让日期列对 desc 进行排序,并在同一个 CASE ORDER BY 语句中将字符串列按 asc 排序?

这就是我现在所拥有的 CASE ORDER BY

    ORDER BY 
    CASE WHEN @OrderBy = 1 THEN CONVERT(NVARCHAR(30) , ccd.CertEndDate) + tp.LastName + tp.FirstName END ,
    CASE WHEN @OrderBy = 2 THEN CONVERT(NVARCHAR(30) , ccd.CertEndDate) + tp.LastName + tp.FirstName END DESC
Run Code Online (Sandbox Code Playgroud)

此代码解析并返回一个结果集没有错误,但第二个 CASE ORDER BY 都是 DESC 排序顺序,当我更喜欢 ccd.CertEndDate DESC , tp.LastName ASC , tp.FirstName ASC

提前致谢。

JNK*_*JNK 6

再分解一下:

ORDER BY CASE WHEN @orderby = 1 THEN CONVERT(NVARCHAR(30) , ccd.CertEndDate) END ASC,
         CASE WHEN @orderby = 2 THEN CONVERT(NVARCHAR(30) , ccd.CertEndDate) END DESC,
         tp.lastname ASC,
         tp.firstname ASC
Run Code Online (Sandbox Code Playgroud)

您只需要更改第一个字段的排序顺序,因此不要将其他字段包含在CASE.

应该注意的是,我们不包括ELSEfor each CASE,这意味着任何其他值都将返回NULL并从ORDER BY.


Pau*_*ite 5

除了 JNK 的回答,您还可以考虑:

DECLARE @Example TABLE
(
    first_name      NVARCHAR(50) NOT NULL,
    last_name       NVARCHAR(50) NOT NULL,
    cert_end_date   DATE NOT NULL,
    other_columns   NCHAR(100) NOT NULL DEFAULT (N'')

    UNIQUE (cert_end_date ASC, first_name, last_name),
    UNIQUE (cert_end_date DESC, first_name, last_name)
)

INSERT @Example
    (first_name, last_name, cert_end_date)
VALUES
    ('a', 'w', '2008-12-31'),
    ('b', 'x', '2009-12-31'),
    ('c', 'y', '2010-12-31'),
    ('d', 'z', '2011-12-31')

DECLARE
    @order_date_ascending BIT = CONVERT(BIT, 'true')

-- 1.  May require an explicit sort despite useful indexes
SELECT
    e.first_name,
    e.last_name,
    e.cert_end_date
FROM @Example AS e
ORDER BY
    CASE WHEN @order_date_ascending = 1 THEN e.cert_end_date END ASC,
    CASE WHEN @order_date_ascending = 0 THEN e.cert_end_date END DESC,
    e.first_name ASC,
    e.last_name ASC

-- 2.  Conditional statements
IF  @order_date_ascending = CONVERT(BIT, 'true')
BEGIN
    SELECT
        e.first_name,
        e.last_name,
        e.cert_end_date
    FROM @Example AS e
    ORDER BY
        e.cert_end_date ASC,
        e.first_name ASC,
        e.last_name ASC
END
ELSE IF @order_date_ascending = CONVERT(BIT, 'false')
BEGIN
    SELECT
        e.first_name,
        e.last_name,
        e.cert_end_date
    FROM @Example AS e
    ORDER BY
        e.cert_end_date DESC,
        e.first_name ASC,
        e.last_name ASC
END

-- 3.  Union All & Start-up Filters
SELECT * FROM 
(
    SELECT TOP (9223372036854775807)
        e.first_name,
        e.last_name,
        e.cert_end_date
    FROM @Example AS e
    WHERE
        @order_date_ascending = CONVERT(BIT, 'true')
    ORDER BY
        e.cert_end_date ASC,
        e.first_name ASC,
        e.last_name ASC
) AS sort_asc
UNION ALL
SELECT * FROM 
(
    SELECT TOP (9223372036854775807)
        e.first_name,
        e.last_name,
        e.cert_end_date
    FROM @Example AS e
    WHERE
        @order_date_ascending = CONVERT(BIT, 'false')
    ORDER BY
        e.cert_end_date DESC,
        e.first_name ASC,
        e.last_name ASC
) AS sort_desc
Run Code Online (Sandbox Code Playgroud)

如果发生语句级编译或使用OPTION (RECOMPILE)查询提示强制发生,则第一种和第三种方法可以受益于 SQL Server 2008 SP1 CU5 上可用的参数嵌入优化。有关详细信息,请参阅此MSDN 博客条目。

第三种方法不需要每次都编译,因为计划中的过滤器操作符有一个启动表达式。每个过滤器下方的计划子树仅在条件评估为真时才执行。