使用变量 Coalesce 进行排序

Mar*_*ukh 1 sql t-sql sql-server

我有以下sql命令

DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',['+ cast(Month as nvarchar(2))+']' , '['+ Cast(Month as nvarchar(2))+']')
FROM    (select distinct Month from Employee  WHERE  Year*100+Month BETWEEN 201704 and 201712 ) as e
PRINT @cols 
Run Code Online (Sandbox Code Playgroud)

结果是

[9],[12],[6],[7],[10],[4],[5],[11],[8]
Run Code Online (Sandbox Code Playgroud)

但我真的希望它能按排序顺序

[4],[5],[6],[7],[8],[9],[10],[11],[12]
Run Code Online (Sandbox Code Playgroud)

Cha*_*ace 6

变量合并记录为不确定性,可能会导致不正确的结果,特别是在存在ORDER BY. 您也不能放置在派生表或视图中,原因很明显:最终顺序由外部查询ORDER BY确定。

您应该只使用STRING_AGG聚合。您可以用来WITHIN GROUP (ORDER BY获取订单。

另请注意:

  • 始终使用QUOTENAME括号将列名括起来,而不是自己这样做,因为转义可能很复杂。
  • 最好对列进行精确比较,而不是对它们进行计算然后进行比较,因为这样您就可以命中索引(监视能力)。
  • 将日期存储在实际日期列中可能比混乱地使用多个列更好,但我会将数据库重新设计留给您
DECLARE @cols NVARCHAR(MAX) = (
    SELECT STRING_AGG(QUOTENAME(Month), N',') WITHIN GROUP (ORDER BY Month)
    FROM (
        select distinct
          Month
        from Employee
        WHERE Year = 2017
          AND Month BETWEEN 4 AND 12
    ) as e
);
Run Code Online (Sandbox Code Playgroud)

对于 SQL Server 2016 及更早版本,您可以使用旧FOR XML方法:

DECLARE @cols NVARCHAR(MAX) = STUFF((
    SELECT N',' + QUOTENAME(Month)
    FROM (
        select distinct
          Month
        from Employee
        WHERE Year = 2017
          AND Month BETWEEN 4 AND 12
    ) as e
    ORDER BY Month
    FOR XML PATH(''), TYPE
  ).value('text()[1]','nvarchar(max)')
  , 1, LEN(N','), N'');
Run Code Online (Sandbox Code Playgroud)