J'ai deux tables: car je dois regarder La sortie souhaitée devrait ressemblent à ceci: strong> p> Le ci-dessous est un exemple avec des données factices pour obtenir le bon maintable code> et
myTable code>. Mytable a un contrôle unique et un identifiant. J'ai besoin d'ajouter un tout premier
effdate code> à partir de
maintable code> à
Mytable code> basé sur
ID code> et
contrôlé code >.
Précédent code> colonne, puis voir si ce
Précédent est dans la colonne code> code> et ainsi de suite. p>
Effilez code> en fournissant une valeur code> code>. Ça fonctionne, mais comment puis-je boucler à travers l'ensemble
gestable code>, récupérer
id code> s et
effondre code> dans une table séparée, puis joindre cette table à MyTable CODE>? P>
-- create sample table #MainTable
IF OBJECT_ID('tempdb..#MainTable') IS NOT NULL DROP TABLE #MainTable;
create table #MainTable (ControlNo int, ID varchar(50), PreviousID varchar(50), EffDate date)
insert into #MainTable values
(3333,'QuoteID3','QuoteID2', '2020-08-25'),
(2222,'QuoteID2','QuoteID1', '2019-08-25'),
(1111,'QuoteID1',NULL, '2018-08-25'),
(7777,'QuoteID6','QuoteID5', '2020-02-10'),
(6666,'QuoteID5',NULL, '2019-02-10')
--select * from #MainTable
-- create sample table #MyTable
IF OBJECT_ID('tempdb..#MyTable') IS NOT NULL DROP TABLE #MyTable;
create table #MyTable (ControlNo int, ID varchar(50), EffDate date)
insert into #MyTable values
(3333,'QuoteID3',NULL),
(7777,'QuoteID6',NULL)
--select * from #MyTable
4 Réponses :
Vous pouvez utiliser un CTE récursif pour ceci:
WITH cte AS ( SELECT m.ID,m.PreviousID FROM MainTable m JOIN MainTable m2 ON m.previousID = m2.ID WHERE m2.previousID IS NULL UNION ALL SELECT m2.ID,cte.previousID FROM cte JOIN MainTable m2 ON m2.previousID = cte.ID ) SELECT * FROM cte;
Utiliser CTE comme ci-dessous, vous pouvez obtenir les résultats souhaités.
voir la démonstration en direct kbd> En savoir plus sur les CTES récursives ici p>
Vous pouvez utiliser une requête récursive pour traverser la hiérarchie.
Je commencerais en rejoignant la table d'origine avec la table principale, qui limite les chemins des lignes que nous sommes intéressés. Ensuite, vous pouvez recourir à la parent. Enfin, nous devons filtrer sur le parent supérieur par chemin suivant: Considérez: p> top () code> et
row_number () code> est utile pour cela. P>
controlno | id | effdate
--------: | :------- | :---------
3333 | QuoteID3 | 2018-08-25
7777 | QuoteID6 | 2019-02-10
Ce n'est pas une bonne solution à première vue. Il n'y a aucune raison de faire la jointure qui coûte beaucoup de coût dans chaque itération de la récursive.
@Ronenarriement: pas du tout. Comme je l'ai expliqué dans ma réponse, la jointure ne se produit que dans l'ancre de la requête, ce qui limite le nombre de rangées que nous devons ensuite faire itérair à ceux que nous avons vraiment besoin.
Merci. C'est bien!
Voici un exemple de travail de l'approche CTE avec la table fournie résultats p>
"Pourquoi voulez-vous faire boucle en premier lieu?" : Probablement depuis qu'il vient du monde en développement et a vu de l'aide pour comprendre que les bases de données tabulaires fonctionnent mieux avec le jeu de lignes et non à la ligne de ligne :-)
Oh, s'il y a une façon, je peux éviter la boucle qui serait génial.
J'ai pensé à utiliser des jointures mais que le nombre de précédents n'est pas constant
Remarque latérale séparée, vous êtes mieux à partir d'une fonction de valeur de table en ligne sur cette fonction scalaire. Il a aussi un
top 1 code>, mais pas de code
par code>, ce qui signifie que une ligne arbitraire i> peut être retourné, ce qui pourrait facilement ne pas être identique une fois chaque fois que vous exécutez ladite fonction.