Encontrar nós folha na árvore hierárquica
Pergunta
Eu tenho uma tabela no meu banco de dados que armazena uma estrutura de árvore. Aqui estão os campos relevantes:
mytree (id, parentid, otherfields...)
Eu quero encontrar todos os nós folha (isto é, qualquer registro cujo id
não é parentid
do outro recorde)
Eu tentei isso:
SELECT * FROM mytree WHERE `id` NOT IN (SELECT DISTINCT `parentid` FROM `mytree`)
Mas que retornou um conjunto vazio. Estranhamente, removendo os "e não" retorna o conjunto de todos os nós não-folha.
Alguém pode ver onde eu estou indo errado?
Atualização: Obrigado pelas pessoas respostas, todos eles têm sido correta e funcionou para mim. Eu aceitei de Daniel, uma vez que também explica por que minha consulta não funcionou (a coisa NULL).
Solução
A sua consulta não funcionou porque o sub-consulta inclui NULL
. A seguir ligeira modificação funciona para mim:
SELECT * FROM `mytree` WHERE `id` NOT IN (
SELECT DISTINCT `parentid` FROM `mytree` WHERE `parentid` IS NOT NULL)
Outras dicas
nenhum indício porque sua consulta não funcionou. Aqui está a coisa idêntica em junção externa esquerda sintaxe -? Experimentá-lo desta maneira
select a.*
from mytree a left outer join
mytree b on a.id = b.parentid
where b.parentid is null
SELECT * FROM mytree AS t1
LEFT JOIN mytree AS t2 ON t1.id=t2.parentid
WHERE t2.parentid IS NULL
SELECT * FROM minhaarvore onde id não em (Selecionar parentid distinto do minhaarvore onde parentid não é null)
http://archives.postgresql.org/pgsql-sql /2005-10/msg00228.php
minha estrutura de tabela é
memberid MemberID joiningposition packagetype
RPM00000 NULL Root free
RPM71572 RPM00000 Left Royal
RPM323768 RPM00000 Right Royal
RPM715790 RPM71572 Left free
RPM323769 RPM71572 Right free
RPM715987 RPM323768 Left free
RPM323985 RPM323768 Right free
RPM733333 RPM323985 Right free
RPM324444 RPM715987 *emphasized text*Right Royal
-
ALTER procedure [dbo].[sunnypro]
as
DECLARE @pId varchar(40) = 'RPM00000';
Declare @Id int
set @Id=(select id from registration where childid=@pId)
begin
-- Recursive CTE
WITH R AS
(
SELECT
BU.DateofJoing,
BU.childid,
BU.joiningposition,
BU.packagetype
FROM registration AS BU
WHERE
BU.MemberID = @pId and
BU.joiningposition IN ('Left', 'Right')
or BU.packagetype in('Royal','Platinum','Majestic')
and BU.Id>@id
UNION All
-- Recursive part
SELECT
BU.DateofJoing,
BU.childid,
R.joiningposition,
BU.packagetype
FROM R
JOIN registration AS BU
ON BU.MemberID = R.childid
WHERE
BU.joiningposition IN ('Left', 'Right') and
BU.packagetype in('Royal','Platinum','Majestic')
and BU.Id>@id
)
INSERT INTO Wallatpayout
(childid
,packagetype
,joiningposition
,DateofJoing
,Total)
-- Final groups of nodes found
SELECT top 3
R.childid,
R.packagetype,
R.joiningposition,
R.DateofJoing,
Total = COUNT_BIG(*)
FROM R where R.packagetype in('Royal','Platinum','Majestic')
GROUP BY R.childid,
R.joiningposition,
R.DateofJoing,
R.packagetype
OPTION (MAXRECURSION 0);
end