2
votes

Tri personnalisé basé sur les enregistrements référencés

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 commentaires

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.


4 Réponses :


3
votes

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


3 commentaires

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.



1
votes

Voici une solution plus simple:

SELECT 
    Id,
    F1,
    F2,
    Ref_ID
FROM 
    @Table
ORDER BY 
    ISNULL(Ref_ID,ID), ID

Résultat:

 entrez la description de l'image ici


2 commentaires

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



0
votes

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


5 commentaires

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



1
votes

En utilisant LINQ, vous pouvez le faire comme ceci:

from i in data
orderby i.Ref_ID ?? i.Id
select i;


0 commentaires