SQL-Schleife über einen Stammbaum
-
25-09-2019 - |
Frage
Verwenden von SQL Server 2008. Ich habe einen Stammbaum der Tiere in einer Tabelle gespeichert, und will einige Informationen darüber, wie ‚genetisch vielfältig‘ (oder auch nicht), um die Nachkommen sind. In SQL wie kann ich produzieren vernünftige Metriken zu zeigen, wie eng verwandt sind die Eltern? Vielleicht eine Art von Prozentsatz des gemeinsamen Blutes oder mehr Generationen zurück zu gehen, bevor es ein gemeinsamer Vorfahr ist?
AnimalTable
Id
Name
mumId
dadId
select * from AnimalTable child
inner join AnimalTable mum on child.[mumId] = mum.[Id]
inner join AnimalTable dad on child.[dadId] = dad.[Id]
inner join AnimalTable mums_mum on mum.[mumId] = mums_mum.[Id]
inner join AnimalTable mums_dad on mum.[dadId] = mums_dad.[Id]
inner join AnimalTable dads_mum on dad.[mumId] = dads_mum.[Id]
inner join AnimalTable dads_dad on dad.[dadId] = dads_dad.[Id]
Lösung
Ich würde vorschlagen, Sie sehen Rekursion einen CTE (Common Table Expression) verwendet wird.
Dies wird Ihnen rekursiv Blick durch die Eltern erlauben, bis ein gemeinsamer Vorfahre unter Beibehaltung einen Wert für diese zu finden ist.
Andere Tipps
WITH hier1(parent, level) AS
(
SELECT mum, 1
FROM AnimalTable a
WHERE a.id = @first_animal
UNION ALL
SELECT dad, 1
FROM AnimalTable a
WHERE a.id = @first_animal
UNION ALL
SELECT mum, level + 1
FROM q
JOIN AnimalTable a
ON a.id = q.parent
UNION ALL
SELECT dad, level + 1
FROM q
JOIN AnimalTable a
ON a.id = q.parent
),
hier2(parent, level) AS
(
SELECT mum, level
FROM AnimalTable a
WHERE a.id = @second_animal
UNION ALL
SELECT dad, level
FROM AnimalTable a
WHERE a.id = @second_animal
UNION ALL
SELECT mum, level + 1
FROM q
JOIN AnimalTable a
ON a.id = q.parent
UNION ALL
SELECT dad, level + 1
FROM q
JOIN AnimalTable a
ON a.id = q.parent
)
SELECT TOP 1
h1.parent,
CASE WHEN h1.level < h2.level THEN h1.level ELSE h2.level END AS minlevel
FROM hier1 h1
JOIN hier2 h2
ON h1.parent = h2.parent
ORDER BY
2
Das kann nicht in einer realistischen fasion beantwortet werden - ignorieren für einen Moment den SQL-Teil, aber Sie nicht einmal wissen, was Sie wollen. „Vielleicht“ - na ja, denke, es ist wieder durch. Was passiert, wenn Sie mehr Teil Vorfahren haben? Was tun Sie dann?
Das Finden alle Vorfahren einer bestimmten Nachkommen trivial ist (temporäre Tabelle, Füllung mit seinen Eltern rekursiv „Generation weg“ als Feld hinzufügen).
Dann können Sie die beiden temporären Tabellen verknüpfen. Nizza bisher (und sorry, das muss im Grunde sein, weil Ihr hierarchiy wieder viele Generationen gehen kann).
Aber von dort kann man noch auf tatsächlich einen vernünftigen Algorithmus finden, was das bedeuten sollte - in nicht-trivialen Szenarien;)