【问题标题】:ORDER BY clause is not sorting by alias in SQL ServerORDER BY 子句在 SQL Server 中未按别名排序
【发布时间】:2015-07-10 01:09:09
【问题描述】:

我有一个这样的查询:

DECLARE @Sortorder VARCHAR(5) = 'asc',
        @ColumnNumber INT = 9

SELECT
    SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, LEN(csu.UserName)) AS UserName, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
WHERE
    w.[ShowInTaskList] = 1 AND UserName IS NOT NULL
ORDER BY
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'asc' THEN UserName END ASC,
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'desc' THEN UserName END DESC

当我这样做时,数据不会按用户名按任何顺序 asc 或 desc 排序,但是当我这样做时:

SELECT
    SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1, LEN(csu.UserName)) AS UserName, w.WorkItemId
FROM [tasks].[WorkItems] w
LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
WHERE
    w.[ShowInTaskList] = 1 AND UserName IS NOT NULL
ORDER BY
    UserName

我在动态顺序中做错了什么?声明的变量和案例中的值相同。坦率地说,我不知道应该将哪些关键字传递给 google ;) 非常感谢您的回答。

【问题讨论】:

  • 如何同时使用用户名 asc 和 desc 进行订购。我错过了什么吗?您的两个订单声明都是真实的。
  • 哇,没想到,谢谢!!请在我的问题下回答,以便我竖起大拇指;)
  • 您认为这两种 order by 语句如何正确?这取决于将存储什么 @SortOrder 变量...
  • hmm 有一个答案,事实上我得到的是 LEN 而不是用户名,并且回答对我有用,当你输入排序顺序时,回答你的问题不是同时asc 它将按 asc 排序,如果 desc 然后 desc 问题是当...的情况下它没有排序

标签: sql sql-server tsql sorting sql-order-by


【解决方案1】:

您拥有列 UserName 和别名 UserNamecolumn 值用于对结果进行排序,而不是别名。虽然在ORDER BY 子句中使用别名是完全可以接受的,但它不能在CASE WHEN 语句中使用。

解决方案是使用子查询(或 CTE):

DECLARE
    @Sortorder VARCHAR(5) = 'asc',
    @ColumnNumber INT = 9

SELECT * FROM (
    SELECT SUBSTRING(csu.UserName, /* removed for readability */) AS UserNameCopy, w.WorkItemId
    FROM [tasks].[WorkItems] w
    LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
    WHERE w.[ShowInTaskList] = 1 AND UserName IS NOT NULL
) AS SubQuery
ORDER BY 
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'asc'  THEN SubQuery.UserNameCopy END ASC,
    CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'desc' THEN SubQuery.UserNameCopy END DESC

【讨论】:

  • 为什么@ColumnNumber = 7 时不会崩溃?我的第一反应是它应该崩溃,因为它就像写order by asc desc(不写任何列名!)但它没有。为什么?
  • @ZoharPeled 因为它将按 null 排序,并且任何硬编码值都是有效的示例:按 null、null、2015、''a' desc 排序
  • @t-clausen.dk:好的,我明白我的错误了,就像写order by null asc, null desc。谢谢!
  • 感谢您的回答。早期的解决方案似乎是正确的,但排序并不好。例如我有三个用户 r.koscinski_some_super_user,some_agent_user。它像这样按升序排列:r.koscinski, some_super_user, some_agent_user,实际上应该是 r.koscinski, some_agent_user, some_super_user 这个子查询会是“治愈”吗?
  • 问题是数据按一组值(用户名)排序,但显示另一组值(用户名的子字符串)。我不确定代理值,建议您检查是否存在相同问题。
【解决方案2】:

您可以使用 CROSS APPLY 使您的代码看起来更友好。它不影响性能:

DECLARE
    @Sortorder VARCHAR(5) = 'asc' ,
    @ColumnNumber INT = 9;

SELECT
    SUBSTRING(csu.UserName, CHARINDEX(CHAR(92), csu.UserName) + 1,
            u.UserName   ,
    w.WorkItemId
FROM
    [tasks].[WorkItems] w
    LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
    CROSS APPLY (SELECT LEN(csu.UserName) AS UserName ) u
WHERE
    w.[ShowInTaskList] = 1
    AND UserName IS NOT NULL
ORDER BY
    CASE WHEN @ColumnNumber = 9
              AND @Sortorder = 'asc' THEN u.UserName
    END ASC ,
    CASE WHEN @ColumnNumber = 9
              AND @Sortorder = 'desc' THEN u.UserName
    END DESC;

数据示例:

CREATE TABLE #a ( aColumn INT, b INT );

INSERT  INTO #a
VALUES
        ( 1, 1 ),
        ( 1, 2 ),
        ( 2, 1 ),
        ( 3, 1 ),
        ( 1, 3 ),
        ( 4, 4 );

DECLARE
    @Sortorder VARCHAR(5) = 'asc' ,
    @ColumnNumber INT = 9;

SELECT
    aColumn ,
    b aColumn
FROM
    #a tbl
    CROSS APPLY (
                  SELECT
                    CAST(( tbl.aColumn + 1 - 2 ) * 5 AS VARCHAR(100)) r /*or any other kind of operation, such as substring etc*/
                ) shortcut
ORDER BY
    CASE WHEN @ColumnNumber = 9
              AND @Sortorder = 'asc' THEN shortcut.r
    END ASC ,
    CASE WHEN @ColumnNumber = 9
              AND @Sortorder = 'desc' THEN shortcut.r
    END DESC;


DROP TABLE #a;

【讨论】:

    【解决方案3】:

    我认为您可以使用 Dynamic SQL 轻松实现这一点(它对我有用):

    DECLARE @statement NVARCHAR(MAX) ,
            @SortOrder VARCHAR(5) = 'desc' ,
            @columnNumber INT = 9
    
    
    SET @statement = N'
    SELECT 
        SUBSTRING(csu.UserName, CHARINDEX('\ ',csu.UserName) + 1, LEN(csu.UserName)) as UserName, w.WorkItemId
    FROM [tasks].[WorkItems] w
        LEFT JOIN operations.CustomerServiceUser csu 
            ON csu.UserId = w.AssignedToUserId
    WHERE       
        w.[ShowInTaskList] = 1 
        AND UserName is not null
    ORDER BY' +            
            CASE 
                WHEN (@ColumnNumber = 9 AND @SortOrder = 'asc') THEN 'UserName ASC'
                WHEN (@columnNumber = 9 AND @SortOrder = 'desc') THEN 'UserName DESC'
                ELSE 'CustomerId' END 
    
    
    EXEC sys.sp_executesql @statement
    GO
    

    【讨论】:

      【解决方案4】:

      我认为简单安全的方法是使用 CTE:

      ;WITH CTE AS
      (
          SELECT ROW_NUMBER() OVER (ORDER BY UserName ASC) As AscOrder,
                 ROW_NUMBER() OVER (ORDER BY UserName DESC) As DescOrder,
              -- editor note: CHARINDEX is for '\' and not '\ ', but it messes up the code coloring system of SO, so I've added a space.
              SUBSTRING(csu.UserName, CHARINDEX('\ ',csu.UserName) + 1,LEN(csu.UserName)) as UserName, w.WorkItemId
          FROM [tasks].[WorkItems] w
          LEFT JOIN operations.CustomerServiceUser csu ON csu.UserId = w.AssignedToUserId
          WHERE w.[ShowInTaskList] = 1 
          AND UserName is not null
      )
      
      SELECT *
      FROM CTE 
      ORDER BY CASE WHEN @ColumnNumber = 9 AND @SortOrder = 'asc' THEN AscOrder
                    WHEN @ColumnNumber = 9 AND @SortOrder = 'desc' THEN DescOrder
               END 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多