ORDER BY 后的 MSSQL CASE 不使用别名

MSSQL CASE after ORDER BY not working with alias

你好 Stack Overflow 社区!

我和我的同事坐在这里,我们正在努力解决我们目前在 MSSQL 2014 中遇到的问题。

我们有一个包含许多列的 table,其中两列包含一个日期。 仅供理解;一个日期 ('Liefertermin') 显示 when/if 它实际交付,另一个日期 ('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 语句

现在我们面临的问题是:

我们无法按上面选择的 'SortDate' 进行排序,如果它位于 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' 但没有成功,还尝试使用派生的 table 但我们得到了相同的结果。

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

真心希望在这里得到帮助! 问候 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

已更新

您需要将当前的 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

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

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

其中 2 是排序日期的列号。

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

或者您可以使用

select * from (

your query
...
) as T1

order by 
case WHEN @Sort = 1 then T1.[Sortdate] END DESC,

.....

您不能在 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

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

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

select * from your_cte order by SortDate

CTE Reference

由于我还无法理解的原因,您似乎无法在使用 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