patternsqlMinor
Order by 1 shortens the result set to one row
Viewed 0 times
resultordertheonerowsetshortens
Problem
I'm running the following query:
But I'm only getting one line printed.
If I take out the
Is this a bug in SQL Server?
I've tried it on SQL SErver 2016 SP1 and 2014 Sp2-Cu1.
DECLARE @sql NVARCHAR(max) = N''
SELECT @sql += N' EXEC dbo.DoSomething @Tablename = ''' + SCHEMA_NAME(T.schema_id) + N'.' + T.name + N''''
--SELECT *
FROM sys.tables T
INNER JOIN sys.indexes I ON I.object_id = T.object_id
ORDER by 1
PRINT @sqlBut I'm only getting one line printed.
If I take out the
ORDER by 1 line, or replace it withORDER BY t.name then I get the expected result.Is this a bug in SQL Server?
I've tried it on SQL SErver 2016 SP1 and 2014 Sp2-Cu1.
Solution
Is this a bug in SQL Server?
No.
From PRB: Execution Plan and Results of Aggregate Concatenation Queries Depend Upon Expression Location
The correct behavior for an aggregate concatenation query is
undefined.
See also this excellent answer by Martin Smith over at stackoverflow.
nvarchar concatenation / index / nvarchar(max) inexplicable behavior
Sometimes it works and sometimes it does not work and that is dependent on the execution plan. The magic works if the compute scalar doing the concatenation is positioned as the first operator below the select operator.
But if you are unlucky you could end up with a different plan. This one has a sort operator between the select and the compute scalar.
The best way to solve this (in my opinion) is to use
Some version of SQL Server in the future will have a built in string aggregate function STRING_AGG (Transact-SQL).
No.
From PRB: Execution Plan and Results of Aggregate Concatenation Queries Depend Upon Expression Location
The correct behavior for an aggregate concatenation query is
undefined.
See also this excellent answer by Martin Smith over at stackoverflow.
nvarchar concatenation / index / nvarchar(max) inexplicable behavior
Sometimes it works and sometimes it does not work and that is dependent on the execution plan. The magic works if the compute scalar doing the concatenation is positioned as the first operator below the select operator.
declare @T table(Name nvarchar(5));
insert into @T values (N'aaaa3'),(N'bbbb2'),(N'cccc1');
declare @S nvarchar(18) = N'';
select @S += ',' + T.Name
from @T as T;But if you are unlucky you could end up with a different plan. This one has a sort operator between the select and the compute scalar.
select @S += ',' + T.Name
from @T as T
order by reverse(T.Name);The best way to solve this (in my opinion) is to use
for xml path to do the concatenation instead.select @S = (
select ',' + T.Name
from @T as T
order by reverse(T.Name)
for xml path(''), type
).value('text()[1]', 'nvarchar(max)');Some version of SQL Server in the future will have a built in string aggregate function STRING_AGG (Transact-SQL).
Code Snippets
declare @T table(Name nvarchar(5));
insert into @T values (N'aaaa3'),(N'bbbb2'),(N'cccc1');
declare @S nvarchar(18) = N'';
select @S += ',' + T.Name
from @T as T;select @S += ',' + T.Name
from @T as T
order by reverse(T.Name);select @S = (
select ',' + T.Name
from @T as T
order by reverse(T.Name)
for xml path(''), type
).value('text()[1]', 'nvarchar(max)');Context
StackExchange Database Administrators Q#156347, answer score: 7
Revisions (0)
No revisions yet.