Dado um esquema como este:
CREATE TABLE Foo
(
Id int PRIMARY KEY,
Position int NOT NULL,
Title varchar(10) NOT NULL
);
INSERT INTO Foo VALUES
(1, 3, 'Title3'),
(2, 10, 'Title10'),
(3, 1, 'Title1'),
(4, 12, 'Title12'),
(5, 2, 'Title2');
Eu preciso gerar uma string separada por vírgulas ordenada por Position
:
'M' + Id + ' AS [' + Title + ']'
Resultado desejado:
M1 AS [Title1], M2 AS [Title10], M3 AS [Title3], M4 AS [Title10], M5 AS [Title12]
Eu tentei:
DECLARE @rows nvarchar(max);
SET @rows = STUFF((SELECT DISTINCT ', ' + ('M' + CAST(Id as varchar(10)) + ' AS ' + QUOTENAME(Title))
FROM Foo
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(MAX)')
,1,1,'');
SELECT @rows;
Mas ele constrói o resultado ordenado por Id
:
M1 AS [Title3], M2 AS [Title10], M3 AS [Title1], M4 AS [Title12], M5 AS [Title2]
Se eu adicionar ORDER BY Id
à STUFF
expressão:
DECLARE @rows nvarchar(max);
SET @rows = STUFF((SELECT DISTINCT ', ' + ('M' + CAST(Id as varchar(10)) + ' AS ' + QUOTENAME(Title))
FROM Foo
ORDER BY Position
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(MAX)')
,1,1,'');
SELECT @rows;
Produz o próximo erro:
Msg 145 Nível 15 Estado 1 Linha 2 Os
itens ORDER BY devem aparecer na lista de seleção se SELECT DISTINCT for especificado. +
Eu posso usar uma subconsulta ordenada por Position
:
DECLARE @rows nvarchar(max);
SET @rows = STUFF((SELECT DISTINCT ', ' + ('M' + CAST(Id as varchar(10)) + ' AS ' + QUOTENAME(Title))
FROM (SELECT TOP 100 PERCENT Id, Position, Title FROM Foo ORDER BY Position) X
FOR XML PATH(''), TYPE
).value('.', 'nvarchar(MAX)')
,1,1,'');
SELECT @rows;
M1 AS [Title3], M2 AS [Title10], M3 AS [Title1], M4 AS [Title12], M5 AS [Title2]
Mas gostaria de saber se existe outra maneira de ordenar o resultado sem usar uma subconsulta. Não há títulos duplicados.
dbfiddle aqui
Como Aaron Bertrand apontou nos comentários, o erro é produzido porque estou usando
SELECT DISTINCT
; e neste exemplo não é necessário. Além disso,ORDER BY
a posição é totalmente válida se o distinto for removido.Se
DISTINCT
for removida a consulta retorna o valor desejado:dbfiddle aqui
Recomendo dar uma olhada neste artigo, recomendado por sp_BlitzErik :
Concatenação Agrupada: Ordenando e Removendo Duplicatas