Eu tenho as seguintes tabelas dentro de um banco de dados:
+-------------+ +-------------+-------------+ +---------------------------+
| project1 | | project2 + | project3 |
+-------------+ +-------------+-------------+ +---------------------------+
| project1_id | | project2_id | project1_id | | project3_id | project2_id |
+-------------+ +-------------+-------------+ +---------------------------+
| hnc1 | | hnc4 | hnc1 | | hnc7 | hnc4 |
| hnc2 | | hnc5 | hnc1 | | hnc8 | hnc4 |
| hnc3 | | hnc6 | hnc3 | | hnc9 | hnc6 |
+-------------+ +-------------+-------------+ +---------------------------+
Eu preciso recuperar todos os descendentes de um determinado ID de todas as três tabelas - incluindo o próprio ID, se ele for encontrado em qualquer tabela.
Por exemplo, se eu consultar usando o ID 'hnc4' , ele deve obter:
+-------------+
| descendants |
+-------------+
| hnc7 |
| hnc8 |
| hnc4 |
+-------------+
Se eu consultar usando o ID 'hnc1' :
+-------------+
| descendants |
+-------------+
| hnc4 |
| hnc5 |
| hnc7 |
| hnc8 |
| hnc1 |
+-------------+
A consulta deve funcionar mesmo que o ID esteja apenas na última tabela project3
.
Eu estava pesquisando e descobri que um CTE recursivo poderia ser útil, mas não sei como fazê-lo com 3 tabelas envolvidas.
Alguma orientação sobre como obter os resultados certos?
Os identificadores não podem ser parametrizados, então não consigo pensar em uma maneira de percorrer várias tabelas com um rCTE.
Assumindo
UNIQUE
ouPRIMARY KEY
restrições em cada tabela, para que não tenhamos que nos preocupar com duplicatas.Envolvi a consulta em uma função SQL para simplificar a passagem do ID:
O
SELECT
onproject2
vai para o CTEp2
, para que possamos reutilizar o resultado para oSELECT
onproject3
. O mesmo não é necessário paraproject1
eproject3
.Ligar:
Produz exatamente o resultado desejado.
violino SQL.
Se as tabelas forem grandes, certifique-se de ter os índices corretos . Relacionado:
Atualização do esquema
Você não precisa de três tabelas para ter uma única herança. Você pode fazer isso com uma única tabela. Isso não é apenas mais rápido e limpo e melhor para manter a integridade, mas permite mais de três níveis de profundidade (n-level)
Agora podemos consultá-lo,
Esse padrão é chamado de "hierarquia de tabela única" ou uma tabela de auto-referência.
Compatível com versões anteriores
Na verdade, se você quiser voltar ao design bobo de três mesas ..
Crie uma visualização que faça essa última consulta,
Apenas continue seguindo isso..
Suas consultas
Para obter todos os ancestrais de
hcn4
ou4
na minha tabela, altere o ponto terminal e construa-o na direção oposta.Quer
hcn1
só precisa mudar paraWHERE id = 1
;O equivalente,
f_all_descendants_of(int)
torna-se,