LINUX.ORG.RU

Строить дерево без удаленных узлов

 ,


0

1

Дерево храниться так:

mysql> select * from job limit 0,2;
+-------+--------------+------------------------------------------------+---------------------+
| jobid | parent_jobid | title                                          | delete              |
+-------+--------------+------------------------------------------------+---------------------+
|     1 |            0 | node1                                          | 1                   |
|     2 |            1 | node2                                          | 0                   |
+-------+--------------+------------------------------------------------+---------------------+
2 rows in set (0.00 sec)
Визуально это выглядит так:

  • node1
    • node2

Задача:

  1. Не показывать пустые удаленные узлы. А не пустые показывать.
★★★★★

как-то так

А пустые неудаленные показываем, верно?

select j.*
from job j
where j.delete = 0 or j.jobid in
	(select j1.jobid
	from job j1
		inner join job j2
		on j2.parent_jobid = j1.jobid)

Не знаю mysql, поэтому в запросе могут быть синтаксические ошибки. И насчет оптимальности не уверен, х.з. как там в mysql оптимизатор работает. Можно также через exists вместо in написать, можно попробовать обойтись одним join без вложенного запроса.

Кстати, а не надо ли удалять вложенные узлы при удалении родительского?

stateofart ()
Ответ на: как-то так от stateofart

А пустые неудаленные показываем, верно?

да

Кстати, а не надо ли удалять вложенные узлы при удалении родительского?

Нет. Я задачу несколько упростил. Выделили именно то счем у меня проблема.

Спасибо за наводку. С синтаксисом разберусь.

petav ★★★★★ ()
Ответ на: комментарий от Dobriy_i_Prostoy

Да слышал, там выборки подобного рода проще делаются.

petav ★★★★★ ()
Ответ на: как-то так от stateofart

А если признак удаленности хранить в отдельной таблице

mysql> select * from status limit 0,1;
+-------+----------+
| jobid | delete   |
+-------+----------+
|     1 |        1 |
+-------+----------+
|     2 |        0 |
+-------+----------+
1 row in set (0.00 sec)
select j.*
from job j INNER JOIN status USING ( jobid ), 
where j.delete = 0 or j.jobid in
	(select j1.jobid
	from job j1
		inner join job j2
		on j2.parent_jobid = j1.jobid)
В таблицу j не попадает объединенная таблица, как понимаю она создается ранее чем INNER срабатывает. Дадите совет?

petav ★★★★★ ()
Ответ на: комментарий от petav

Может нужно в вашем варианте заменить проверку j.delete = 0 на что-то вроде s.delete = 0 и добавить алиас s для status. Иначе вообще ваш запрос подозрительно выглядит, т.к. вы джойните с таблицей status, но фактически не используете значения из неё. Так и задумано?

stateofart ()
Ответ на: комментарий от stateofart

Так и задумано?

Я SQL плохо знаю.

Может нужно в вашем варианте заменить проверку j.delete = 0 на что-то вроде s.delete = 0 и добавить алиас s для status.

Если времени не жалко. Черкните примерчик.

petav ★★★★★ ()
Последнее исправление: petav (всего исправлений: 1)
Ответ на: комментарий от petav

пожалуйста

select j.*
from job j INNER JOIN status s USING ( jobid ), 
where s.delete = 0 or j.jobid in
	(select j1.jobid
	from job j1
		inner join job j2
		on j2.parent_jobid = j1.jobid)
stateofart ()
Ответ на: пожалуйста от stateofart

Спасибо, работает. Но если в ветке все узлы удалены, то корневой узел запрос отображает.

petav ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.