Veuillez prendre en compte ces données:
Id F1 F2 Ref_ID ------------------------------------------- 1 Nima 35 Null 3 Arian 5 1 4 Ava 1 1 6 Rozhan 30 1 2 Eli 33 Null 5 Arsha 3 2 7 Zhina 20 2
Je souhaite trier ce tableau comme suit:
Id F1 F2 Ref_ID ------------------------------------------- 1 Nima 35 Null 2 Eli 33 Null 3 Arian 5 1 4 Ava 1 1 5 Arsha 3 2 6 Rozhan 30 1 7 Zhina 20 2
les enregistrements référencés doivent être placés sous l'enregistrement de référence basé sur l'ID croissant.
Comment puis-je faire cela en utilisant LINQ
ou SQL
. Merci
4 Réponses :
En SQL, vous pouvez le trier en utilisant un COALESCE
ou ISNULL
pour le Ref_id et l'ID.
Et un IIF
ou un CASE WHEN
pour vous assurer que l'id parent vient en premier dans le même groupe de Ref_id.
SELECT Id, F1, F2, Ref_ID FROM YourTable ORDER BY COALESCE(Ref_ID, Id), IIF(Ref_ID IS NULL, 0, 1), Id;
Un test sur db fiddle ici
Vous pouvez supprimer le IIF retournant 0 ou 1 et simplement trier par identifiant uniquement :)
@PratikBhavsar Cela suffirait pour l'ensemble d'échantillons. Et si Ref_ID est une clé étrangère sur l'ID, vous pouvez supposer que le parent a toujours l'ID le plus bas d'un groupe. Mais cet IIF s'en assure, même si le parent n'a pas l'ID le plus bas. :)
Ouais, j'ai juste supposé qu'il s'agissait d'une clé étrangère et que l'identifiant du parent sera toujours le plus bas.
Voici une solution plus simple:
SELECT Id, F1, F2, Ref_ID FROM @Table ORDER BY ISNULL(Ref_ID,ID), ID
Résultat:
Merci, cela fonctionne mais je ne comprends pas ISNULL
dans la clause de commande. Il semble qu'il renvoie Id
ou Ref_ID
au lieu de leurs valeurs. Est-ce vrai?
@Arian Il renvoie l'ID si Ref_ID est nul sinon Ref_ID. Imaginez-le comme une colonne calculée. Dans votre cas, la colonne ressemblera à 1,1,1,1,2,2,2
Une autre solution consiste à ajouter une colonne supplémentaire dans la requête et à trier sur cette colonne
select t.* from ( select Id, F1, F2, Ref_ID, coalesce(Ref_ID, Id) as RefID_or_Id, iif(Ref_ID is null, 0, 1) as Ref_ID_0_or_1 from YourTable ) t order by t.RefID_or_Id, t.Ref_ID_0_or_1, t.Id
Dans le cas où votre table est volumineuse, vous devez tester laquelle des solutions ici fonctionne le mieux vous
Désolé pour cela, mais vous utilisez inutilement des sous-requêtes et des performances épuisantes, vous pouvez simplement utiliser cette expression pour la colonne calculée dans l'ordre par clause. J'espère que cela t'aides.
@PratikBhavsar Je ne sais pas si c'est vrai. L'utilisation de coalesce
et iff
dans une clause where signifie que sqlserver ne peut pas utiliser d'index. J'ai trouvé que de cette façon, une requête peut en fait mieux fonctionner. C'est pourquoi j'ai également écrit qu'il doit tester les performances, car cela peut dépendre de son schéma de table que nous ne connaissons pas
@PratikBhavsar De plus, l'utilisation d'une sous-requête
comme celle-ci ne videra pas du tout les performances, la seule chose qui peut réduire les performances sont les fonctions appelées. C'est le cas dans chaque réponse ici. J'offre simplement une alternative lorsque la performance est mauvaise dans l'une des autres réponses.
Exactement, nous ne connaissons pas le schéma, j'ai donc décidé de ne pas me soucier des index. En tout cas, merci de l'avoir fait savoir.
@PratikBhavsar Cela me laisse encore me demander pourquoi j'ai obtenu un vote défavorable
En utilisant LINQ, vous pouvez le faire comme ceci:
from i in data orderby i.Ref_ID ?? i.Id select i;
Qu'avez-vous essayé et comment avez-vous échoué?
@PauloMorgado Je rejoins mais je n'ai pas pu générer de résultat avec la jointure dans
LINQ
Je n'ai aucune idée de votre ordre de tri. Pourquoi Nima est-il avant les éléments avec Ref_Id 1, et pourquoi Eli les suit-il?
Montrez-nous du code.