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:
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.