与 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,'')
我有一个 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,'')