SQL Server: parameters ORDER BY dans l'instruction IN

J'ai une instruction SQL qui est la suivante:

SELECT A.ID, A.Name FROM Properties A WHERE A.ID IN (110, 105, 104, 106) 

Lorsque j'exécute cette instruction SQL, la sortie est ordonnée automatiquement en fonction de la list IN par ID et renvoie

  104 West 105 East 106 North 110 South 

Je veux savoir s'il est possible de order par ordre les parameters listés dans la clause IN. donc ça reviendrait

  110 South 105 East 104 West 106 North 

Je pense que le moyen le plus simple dans SQL Server est d'utiliser un JOIN avec des VALUES :

 SELECT p.ID, p.Name FROM Properties p JOIN (VALUES (110, 1), (105, 2), (104, 3), (106, 4)) ids(id, ordering) ON p.id = a.id ORDER BY ids.ordering; 

Sûr…

il suffit d'append une clause Order avec un cas dedans

  SELECT A.ID, A.Name FROM Properties A WHERE A.ID IN (110,105,104,106) Order By case A.ID when 110 then 0 when 105 then 1 when 104 then 2 when 106 then 3 end 

A l'aide d'une fonction d'parsing syntaxique qui returnne la séquence

 SELECT B.Key_PS , A.ID , A.Name FROM Properties A Join (Select * from [dbo].[udf-Str-Parse]('110,105,104,106',',')) B on A.ID=B.Key_Value WHERE A.ID IN (110,105,104,106) Order by Key_PS 

L'UDF si vous avez besoin

 CREATE FUNCTION [dbo].[udf-Str-Parse] (@Ssortingng varchar(max),@Delimeter varchar(10)) --Usage: Select * from [dbo].[udf-Str-Parse]('Dog,Cat,House,Car',',') -- Select * from [dbo].[udf-Str-Parse]('John Cappelletti was here',' ') -- Select * from [dbo].[udf-Str-Parse]('id26,id46|id658,id967','|') -- Select * from [dbo].[udf-Str-Parse]('hello world. It. is. . raining.today','.') Returns @ReturnTable Table (Key_PS int IDENTITY(1,1), Key_Value varchar(max)) As Begin Declare @XML xml;Set @XML = Cast('<x>' + Replace(@Ssortingng,@Delimeter,'</x><x>')+'</x>' as XML) Insert Into @ReturnTable Select Key_Value = lsortingm(rsortingm(Ssortingng.value('.', 'varchar(max)'))) FROM @XML.nodes('x') as T(Ssortingng) Return End 

L'parsingur seul reviendrait

 Select * from [dbo].[udf-Str-Parse]('110,105,104,106',',') Key_PS Key_Value 1 110 2 105 3 104 4 106 

Ce que vous pourriez potentiellement faire est:

  1. Créez un TVF qui splitait la string et conserverait l'ordre original.

Cette question semble avoir déjà écrit cette fonction: MS SQL: Choisissez parmi une string fractionnée et gardez l' ordre d'origine ( gardez à l'esprit qu'il pourrait y avoir d'autres approches, pas seulement celles couvertes dans cette question, je l'ai juste donné comme exemple pour comprendre quelle fonction devrait faire )

Alors maintenant, si vous exécutez cette requête:

 SELECT * FROM dbo.Split('110,105,104,106', ',') AS T; 

Cela ramènerait cette table en conséquence.

 items rownum ------------ 110 1 105 2 104 3 106 4 

Suite à cela, vous pouvez simplement interroger votre table, join avec ce TVF en passant vos identifiants comme paramètre:

 SELECT P.ID, P.Name FROM Properties AS P INNER JOIN dbo.Split('110,105,104,106', ',') AS T ON T.items = P.ID ORDER BY T.rownum; 

Cela devrait conserver l'ordre des parameters.

Si vous avez besoin de meilleures performances, je vous conseille de mettre les loggings de TVF dans la table de hachage, de l'indexer et de vous joindre à la table actuelle. Voir la requête ci-dessous:

 SELECT T.items AS ID, T.rownum AS SortOrder INTO #Temporary FROM dbo.Split('110,105,104,106', ',') AS T; CREATE CLUSTERED INDEX idx_Temporary_ID ON #Temporary(ID); SELECT P.ID, P.Name FROM Properties AS P INNER JOIN #Temporary AS T ON T.ID = P.ID ORDER BY T.SortOrder; 

Cela devrait fonctionner mieux sur des sets de données plus grands et tout aussi bien sur de petits sets de données.

Voici une solution qui ne repose pas sur des valeurs de codes durs ou SQL dynamic (pour éliminer les valeurs de encoding dur).

Je voudrais build une table (peut-être temp ou variable) avec OrderByValue et OrderBySort et insert à partir de l'application.

 OrderByValue OrderBySort 110 1 105 2 104 3 106 4 

Ensuite, je voudrais join la valeur et sortinger par le sorting. La jointure sera la même que la clause In.

 SELECT A.ID, A.Name FROM Properties A JOIN TempTable B On A.ID = B.OrderByValue Order By B.OrderBySort 

Une autre solution pour ce problème est de préparer une table temporaire pour la clause IN comme

 declare @InTable table (ID int, SortOrder int not null identity(1,1)); 

Nous pouvons remplir cette table temporaire avec vos données dans l'ordre que vous voulez

 insert into @InTable values (110), (105), (104), (106); 

Enfin, nous devons modifier votre question pour utiliser cette table temporaire comme celle-ci

 select A.ID, A.Name from Properties A inner join @InTable as Sort on A.ID = Sort.ID order by Sort.SortOrder 

Sur la sortie, vous pouvez voir ceci

 ID Name 110 South 105 East 104 West 106 North 

Dans cette solution, vous n'avez pas besoin de fournir une command spéciale. Vous avez juste besoin d'insert des valeurs dans l'ordre que vous voulez.