【问题标题】:MSSQL CASE after ORDER BY not working with aliasORDER BY 后的 MSSQL CASE 不使用别名
【发布时间】:2017-09-25 12:17:21
【问题描述】:

你好 Stack Overflow 社区!

我和我的同事坐在这里,我们正在尝试解决我们目前在使用 MSSQL 2014 时遇到的问题。

我们有一个包含许多列的表,其中两个包含一个日期。 只是为了理解;一个日期 ('Liefertermin') 显示实际交付时间/是否实际交付,另一个日期 ('FreiesDatum1') 显示计划交付时间。

如果 'Liefertermin' 不为空,那么它应该出现,否则应该出现 'FreiesDatum1'。 我们通过以下查询解决了这个问题:

SELECT
    CASE
       WHEN Liefertermin is null THEN cast(FreiesDatum1 as date)
       ELSE Liefertermin
    END as SortDate
FROM Beleg

在 SELECT 查询中当然还有其他一些列,但这些对于问题来说不是必需的。我们想要动态排序,所以我们可以在不同的类型之间进行选择。为此,我们在开头声明了一个变量 (@Sort),并在“order by”之后设置了一个 CASE-Statement。

现在我们面临的问题是:

如果在 CASE 语句中,我们无法按上面选择的“排序日期”进行订购。如果我们只做order by 'SortDate',它就可以正常工作。

这是我们的尝试,但不起作用:

order by CASE
            when @Sort=1 then 'SortDate'
            when @Sort=2 then 'Liefertermin'
            when @Sort=3 then 'Name'
          END

@Sort=1 没有,但 @Sort=2 和 @Sort=3 确实有效,所以我想 CASE 本身没有问题。删除标记时出现错误,“SortDate”列不存在。

我们已经尝试将别名更改为 [SortDate] 或“SortDate”,但没有成功,还尝试使用派生表,但结果相同。

我们在这里搜索了这些论坛,并尝试了所有适用于 CASE 语句的其他问题的解决方案,但都没有奏效。

真的希望在这里得到帮助! 问候 3m7ecc

编辑:

这是完整的 SQL 查询

Declare @Sort integer;
Set @Sort = 1

select
    Beleg.Belegnummer,
    Beleg.Belegtyp,
    Beleg.Datum,
    wp.Projekt,
    wp.Bezeichnung as 'Projektbezeichnung',
    BELEG.Adressnummer,
    BELEG.Firma,
    BELEG.Ort,
    convert(varchar(10),BELEG.Liefertermin,104) as Liefertermin,
    convert(varchar(10),BELEG.FreiesDatum1,104) as iLiefertermin,
    Beleg.Netto,
    BELEG.Status,
    cast(BELEG.Datum as date) as Erfassungsdatum,
    CASE
        when BELEG.Liefertermin is null then Beleg.FreiesDatum1
        else BELEG.Liefertermin
    END as SortDate
from BELEG
left join WPROJEKT as WP on (wp.Id = BELEG.Projekt)
    where 
    (('01.09.2017' is null or convert(varchar(10),BELEG.Liefertermin,104) >= '01.09.2017')
        and ('31.10.2017' is null or convert(varchar(10),BELEG.Liefertermin,104) <= '31.10.2017')) 
    and Beleg.belegtyp = 'B'
    and ((BELEG.Liefertermin is null
    and BELEG.FreiesDatum1 is null)
    or (BELEG.Liefertermin <= GETDATE() or BELEG.FreiesDatum1 <= GETDATE()))

ORDER BY
CASE WHEN @Sort = 1 then SortDate END DESC,
CASE WHEN @Sort = 2 then Liefertermin END DESC,
CASE WHEN @Sort = 3 then BELEG.Belegnummer END DESC

【问题讨论】:

  • 我认为“SortDate”的顺序不能正常工作。我建议您使用不带单引号的白色列名称,使用 [SortDate] 或 [Liefertermin] 之类的名称;
  • 您按常量排序,在每种情况下:'SortDate' 是一个字符串,而不是对SortDate 列的引用。我想你想删除'
  • 首先感谢您的快速帮助,但正如我所说,当我删除标记时出现错误,该列不存在!
  • 能否在查询中使用列的序号,例如ORDER BY 7?
  • @No'amNewman 是的,我可以使用它,但它不会对其进行排序..

标签: sql sql-server case sql-server-2014 alias


【解决方案1】:

您不能在 ORDER BY 子句中使用别名列,因为在逻辑上排序发生在 SELECT 子句之前。您可以使用列号,例如ORDER BY 9 将按您的“Liefertermin”列对输出进行排序,但这被认为是一种不好的做法。最好的解决方法是将所有内容放在子查询中,例如:

SELECT * FROM
(SELECT... -- your whole select here without the ORDER BY clause
 ) as t1
ORDER BY
    CASE WHEN @Sort = 1 then SortDate END DESC
    CASE WHEN @Sort = 2 then Liefertermin END DESC
    CASE WHEN @Sort = 3 then Name END DESC

【讨论】:

  • 我已经尝试过使用数字,但没有成功,但子查询似乎有效!唯一奇怪的是,我之前尝试过,但没有成功。也许我之前尝试过时忘记了一些东西。非常感谢!
【解决方案2】:

更新

您需要将当前的 select 语句包装在父 SELECT * FROM 中,然后在末尾添加 order by 语句,如下所示:

SELECT * FROM (
    SELECT
        Beleg.Belegnummer,
        Beleg.Belegtyp,
        Beleg.Datum,
        wp.Projekt,
        wp.Bezeichnung as 'Projektbezeichnung',
        BELEG.Adressnummer,
        BELEG.Firma,
        BELEG.Ort,
        convert(varchar(10),BELEG.Liefertermin,104) as Liefertermin,
        convert(varchar(10),BELEG.FreiesDatum1,104) as iLiefertermin,
        Beleg.Netto,
        BELEG.Status,
        cast(BELEG.Datum as date) as Erfassungsdatum,
        CASE
            when BELEG.Liefertermin is null then Beleg.FreiesDatum1
            else BELEG.Liefertermin
        END as SortDate
    FROM BELEG
    LEFT JOIN WPROJEKT as WP on (wp.Id = BELEG.Projekt)
        where 
        (('01.09.2017' is null or convert(varchar(10),BELEG.Liefertermin,104) >= '01.09.2017')
            and ('31.10.2017' is null or convert(varchar(10),BELEG.Liefertermin,104) <= '31.10.2017')) 
        and Beleg.belegtyp = 'B'
        and ((BELEG.Liefertermin is null
        and BELEG.FreiesDatum1 is null)
        or (BELEG.Liefertermin <= GETDATE() or BELEG.FreiesDatum1 <= GETDATE()))
) AS NewBeleg

ORDER BY
    CASE WHEN @Sort = 1 then NewBeleg.SortDate END DESC
    CASE WHEN @Sort = 2 then NewBeleg.Liefertermin END DESC
    CASE WHEN @Sort = 3 then NewBeleg.Name END DESC

【讨论】:

  • 感谢您的帮助,但这也不起作用。它会引发错误,“SortDate”是无效的列名!如果我在 SortDate 周围加上 CASE 中的“SortDate”之类的标记,它就不会做任何事情。没有错误,但也没有排序。
  • 您可以按照您尝试的顺序发布整个 SQL 语句吗?在“SortDate”周围添加标记时,它将按字符串“SortDate”排序,这就是它与标记一起使用的原因
  • 这应该可以。你注意到有三个不同的case 表达式。
  • 你可以试试:BELEG.SortDate 吗?按顺序添加。 WPROJEKT 表中有另一个 SortDate 字段吗? (通过上面的代码更新了订单)
  • 这也不起作用,因为 SortDate 不是 BELEG 表的一部分。我得到与未知列相同的错误。
【解决方案3】:

由于我还无法理解的原因,您似乎无法在使用CASEORDER BY 中使用列别名。 您必须重新输入原始案例语句,然后在 ORDER BY CASE 中进行下一步,例如

    ORDER BY
    CASE WHEN @Sort = 1 then (CASE
                                when BELEG.Liefertermin is null then Beleg.FreiesDatum1
                                else BELEG.Liefertermin
                              END) END DESC
    CASE WHEN @Sort = 2 then NewBeleg.Liefertermin END DESC
    CASE WHEN @Sort = 3 then NewBeleg.Name END DESC

由于@Sort 只能等于一个值,尽管您只需要 1 个案例,例如

    ORDER BY
    CASE WHEN @Sort = 1 then (CASE
                                when BELEG.Liefertermin is null then Beleg.FreiesDatum1
                                else BELEG.Liefertermin
                              END) DESC
         WHEN @Sort = 2 then NewBeleg.Liefertermin DESC
         WHEN @Sort = 3 then NewBeleg.Name DESC

【讨论】:

    【解决方案4】:

    您可以使用 CTE 并避免声明变量,更简洁的方法!

    with your_cte as (
      select isnull(Liefertermin, FreiesDatum1) as SortDate
      from beleg
    )
    
    select * from your_cte order by SortDate
    

    CTE Reference

    【讨论】:

      【解决方案5】:

      您可以在 order by 子句中给出列号而不是列名 喜欢

      order by
      CASE WHEN @Sort = 1 then 2 END DESC
      

      其中 2 是 Sortdate 的列号。

      否则,不要使用别名,而是使用 [tablename].[columname]。

      或者你可以使用

      select * from (
      
      your query
      ...
      ) as T1
      
      order by 
      case WHEN @Sort = 1 then T1.[Sortdate] END DESC,
      

      ....

      【讨论】:

        猜你喜欢
        • 2012-08-31
        • 1970-01-01
        • 1970-01-01
        • 2011-09-21
        • 1970-01-01
        • 1970-01-01
        • 2017-04-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多