sql - 按使用 case 表达式内的别名的计算列进行排序

标签 sql sql-server t-sql sql-order-by

在使用具有别名的计算列时,我的 order by 子句遇到问题,如下所示:

这个order by工作没有任何问题

declare @Mode int = 1
declare @Sort nvarchar(max) = 'engname'

select top 10 School.Id          as EntityId,
              School.EnglishName as EntityEnglishName,
              School.Name        as EntityNativeName,
              case
                  when @Mode = 0 then 0
                  when @Mode = 1 then 1
                  when @Mode = 2 then 2
                  end as ActiveStudents
from V_SchoolMinimized as School
Order By ActiveStudents

以下查询有错误:

Invalid column name 'ActiveStudents'

declare @Mode int = 1
declare @Sort nvarchar(max) = 'engname'

select top 10 School.Id          as EntityId,
       School.EnglishName as EntityEnglishName,
       School.Name        as EntityNativeName,
       case
           when @Mode = 0 then 0
           when @Mode = 1 then 1
           when @Mode = 2 then 2
           end as ActiveStudents
from V_SchoolMinimized as School
Order By
    case when @Sort is null then School.Id end,
    case when @Sort = 'engname' then ActiveStudents end

如何在条件 order by 子句中使用 ActiveStudents(如图所示)?

最佳答案

因此,虽然您可以在 ORDER BY 子句中使用计算列(但不能在 GROUP BY 等其他子句中使用),但您无法应用进一步的计算或条件- 必须完全按照创建时的情况使用。

有很多方法可以解决这个问题。您使用哪种方法将归结为以下一些组合:

  • 作为开发者,您更清楚哪个选项
  • 哪个选项效果更好
  • 哪个选项更适合您现有的查询

选项 1:重复逻辑

我不推荐此选项,因为它违反了 DRY 原则,从而使其更难维护并且更容易犯错误。

select top 10
    S.Id as EntityId
    , S.EnglishName as EntityEnglishName
    , S.[Name] as EntityNativeName
    , case
          when @Mode = 0 then 0
          when @Mode = 1 then 1
          when @Mode = 2 then 2
      end as ActiveStudents
from V_SchoolMinimized as S
order by
    case when @Sort is null then S.Id end
    , case when @Sort = 'engname' then
        case
            when @Mode = 0 then 0
            when @Mode = 1 then 1
            when @Mode = 2 then 2
        end
    end;

其余选项是子查询变体,其选择取决于开始时提供的注释。

选项 2:使用派生表子查询

select top 10
    S.Id as EntityId
    , S.EnglishName as EntityEnglishName
    , S.[Name] as EntityNativeName
    , S.ActiveStudents
from (
    select *
        , case
              when @Mode = 0 then 0
              when @Mode = 1 then 1
              when @Mode = 2 then 2
          end as ActiveStudents
    from V_SchoolMinimized
) as S
order by
    case when @Sort is null then S.Id end
    , case when @Sort = 'engname' then S.ActiveStudents end;

选项 3:使用 CTE(公用表表达式)

with cte as (
    select *
        , case
              when @Mode = 0 then 0
              when @Mode = 1 then 1
              when @Mode = 2 then 2
          end as ActiveStudents
    from V_SchoolMinimized
)
select top 10
    S.Id as EntityId
    , S.EnglishName as EntityEnglishName
    , S.[Name] as EntityNativeName
    , S.ActiveStudents
from cte
order by
    case when @Sort is null then S.Id end
    , case when @Sort = 'engname' then S.ActiveStudents end;

选项 4:使用CROSS APPLY

select top 10
    S.Id as EntityId
    , S.EnglishName as EntityEnglishName
    , S.[Name] as EntityNativeName
    , A.Students
from V_SchoolMinimized as S
cross apply (
    values (
        case
            when @Mode = 0 then 0
            when @Mode = 1 then 1
            when @Mode = 2 then 2
            end
    )
) as A (Students)
order by
    case when @Sort is null then S.Id end
    , case when @Sort = 'engname' then A.Students end;

注意:我建议保持表别名简洁明了,尽可能使用 1-2 个字符,偶尔为 3 个字符。

关于sql - 按使用 case 表达式内的别名的计算列进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71963215/

相关文章:

sql - 如何使用旧列的别名对新创建的列进行分组?

sql - 在 sql 脚本中循环以创建模式

sql - 如何在查询中的两个列名称之间添加 'n' 个空格?

sql-server - 存储与数据库无关的模式

sql - 行为取决于 sql server 版本

t-sql - 如何在SQL中计算平均日期出现频率

sql - 如何在 Microsoft Visual FoxPro 9 中执行自定义函数?

mysql - SQL SELECT 查询在最后一辆车前附加一个 "and"

c# - 如何在 SQL 事件探查器中查看 SQL 查询?

database - 复杂的 SQL 连接