Pergunta

Usando o SQL Server 2008. Tenho uma árvore genealógica de animais armazenada em uma mesa e quero fornecer algumas informações sobre como é 'geneticamente diversificado' (ou não) a prole é. No SQL, como posso produzir métricas sensatas para mostrar quão intimamente relacionados os pais estão? Talvez algum tipo de porcentagem de sangue compartilhado, ou várias gerações para voltar antes de haver um ancestral compartilhado?

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]
Foi útil?

Solução

Eu sugiro que você veja a recursão usando um CTE (expressão comum da tabela).

Isso permitirá que você procure recursivamente os pais até que um ancestral comum seja encontrado, mantendo um valor para isso.

Outras dicas

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

Isso não pode ser respondido em uma fasão realista - ignore a parte SQL por um momento, mas você nem sabe o que deseja. "Talvez" - bem, pense novamente. E se você tiver vários ancestrais parciais? O que fazes, então?

Encontrar todos os ancestrais de uma determinada prole é trivial (tabela de temperatura, preencha com os pais recursivamente, adicionando "geração de distância" como campo).

Então você pode se juntar às duas tabelas temporárias. Bom até agora (e desculpe, isso basicamente tem que ser, porque sua hierarquia pode ir de volta a muitas gerações).

Mas a partir daí você ainda precisa encontrar um algoritmo sensato sobre o que isso significa - em cenários não triviais;)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top