У меня есть таблица в моей базе данных, в которой хранится древовидная структура. Вот соответствующие поля:
mytree (id, parentid, otherfields...)
Я хочу найти все листовые узлы (то есть любую запись, id которой не является parentid другой записи)
Я пробовал это:
SELECT * FROM mytree WHERE `id` NOT IN (SELECT DISTINCT `parentid` FROM `mytree`)
Но это вернуло пустой набор. Как ни странно, удаление «НЕ» возвращает набор всех нелистовых узлов.
Может ли кто-нибудь увидеть, где я ошибаюсь?
Обновлять: Спасибо за ответы, ребята, все они были правильными и работали для меня. Я принял запрос Даниэля, поскольку он также объясняет, почему мой запрос не работал (вещь NULL).
Вообще-то, нет. Любая наполовину приличная РСУБД при необходимости оптимизирует одну в другую. Лучше всего использовать ту форму, которая наиболее четко выражает ваши намерения. В этом случае эта форма почти несомненно является подзапросом.


Понятия не имею, почему ваш запрос не сработал. Вот то же самое в синтаксисе левого внешнего соединения - попробовать так?
select a.*
from mytree a left outer join
mytree b on a.id = b.parentid
where b.parentid is null
Ваш запрос не сработал, потому что подзапрос включает NULL. У меня работает следующая небольшая модификация:
SELECT * FROM `mytree` WHERE `id` NOT IN (
SELECT DISTINCT `parentid` FROM `mytree` WHERE `parentid` IS NOT NULL)
Как мы можем получить листовые узлы от определенного предка?
SELECT * FROM mytree AS t1
LEFT JOIN mytree AS t2 ON t1.id=t2.parentid
WHERE t2.parentid IS NULL
Select * from mytree where id not in (Select distinct parentid from mytree where parentid is not null)
http://archives.postgresql.org/pgsql-sql/2005-10/msg00228.php
моя структура таблицы
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
хм .. вопрос или ответ что ли? Честно говоря, не понимаю, что вы пытаетесь сказать :)
На самом деле гораздо лучше использовать предложенный синтаксис соединения, а не подзапрос.