与 COALESCE 一起使用时,排序方式如何影响分配

How does Order by affect assignment when used along with COALESCE

我有一个 T-SQL 变量,我正在使用 SELECT 操作为其赋值。由于 "SELECT" 查询可能 return 多行,因此我使用 COALESCE 函数附加所有由逗号分隔的值。到目前为止,所有好的查询都按预期运行。但是当我尝试使用 order by 子句对我的值进行排序时,只有一行附加到变量。

为什么在查询 2 中添加 Order By 子句会产生与查询 1 如此不同的结果?

[结果 1]:

Ball 1,Ball 2,Bat 3,Bat 1,Bat 2

[结果 2]:

Bat 1

JS Fiddle link : http://sqlfiddle.com/#!6/8dad1/15

[SQL Fiddle][1]

MS SQL Server 2014 架构设置:

CREATE TABLE tbl_Trans
([Id] int, [Instrument] varchar(20), [Trans_Type] int, [Quantity] int);

CREATE TABLE tbl_Trans_Type
([Id] int, [Trans_Type] varchar(20));  

INSERT INTO tbl_Trans  ([Id], [Instrument], [Trans_Type], [Quantity])

VALUES  
(1,'Ball 1', 121, 50),
(2,'Ball 2', 121, 20),
(3,'Bat 3', 122, 1000),
(4,'Bat 1', 124, 400),
(5,'Bat 2', 121, 300);


INSERT INTO tbl_Trans_Type  ([Id], [Trans_Type])

VALUES 
(121,'Buy'),
(122,'Sell'),
(123,'ReSell'),
(124,'Rent')

**Query 1**:

DECLARE @ST VARCHAR(500) = NULL
SELECT @ST = COALESCE(@ST+ ',' , '')+Instrument 
FROM tbl_Trans a
LEFT JOIN tbl_Trans_Type b on a.Trans_Type = b.Id 

SELECT @ST

[结果 1]:

| Ball 1,Ball 2,Bat 3,Bat 1,Bat 2 |

查询 2:

DECLARE @ST2 VARCHAR(500) = NULL
SELECT  @ST2 = COALESCE(@ST2+ ',' , '')+Instrument 
FROM tbl_Trans a
LEFT JOIN tbl_Trans_Type b on a.Trans_Type = b.Id 
ORDER BY IIF(b.Trans_Type='Buy',1,2)

SELECT  @ST2

[结果 2]:

| Bat 1 |

如果你想连接但有顺序,试试这个:

SELECT STUFF
(
    (
        SELECT ',' +Instrument 
        FROM tbl_Trans a
        LEFT JOIN tbl_Trans_Type b 
            on a.Trans_Type = b.Id 
        ORDER BY IIF(b.Trans_Type='Buy',1,2)
        FOR XML PATH(''), TYPE
    ).value('.', 'VARCHAR(MAX)')
    ,1
    ,1
    ,''
);

您看到的行为是设计使然。在带有 ORDER BY 子句的查询中使用赋值操作(在这种情况下是串联)具有未定义的行为。

使用以下查询将行成功转换为带有 order by 子句的逗号分隔值

select stuff((select ','+Instrument 
FROM tbl_Trans a
  LEFT JOIN tbl_Trans_Type b on a.Trans_Type = b.Id 
ORDER BY IIF(b.Trans_Type='Buy',1,2)
for xml path('')) ,1,1,'')