Возвращает пустой рекурсивный mysql, если один из элементов не совпадает с where

#sql #mariadb #recursive-query

#sql #mariadb #рекурсивный запрос

Вопрос:

У меня есть рекурсивный запрос, который возвращает все элементы до родительского элемента, но мне нужно, чтобы он не возвращал никакого результата, если какой-либо из элементов имеет значение active = 0 .

таблица organigram:

idElement idClient idSubClient idSport idCategory idTeam idParent активный
1 1 -1 (null) (null) (null) (null) 1
2 1 -1 30 (null) (null) 1 1
3 1 -1 (null) 100 (null) 2 0
4 1 -1 (null) (null) 120 3 1
5 1 -1 35 (null) (null) 1 1
6 1 -1 (null) 125 (null) 5 1
7 1 -1 (null) (null) 130 6 1

таблица organigram_users:

idRef idElement idUser активный
1 4 50 1
1 7 50 1

Обратный запрос:

 with recursive elem as (
   select elem.idUser, elem.idElement as root, o.idElement, o.idParent, o.idSport, o.active
   from organigram_users elem
   join organigram o on o.idElement = elem.idElement
   where elem.idUser = 50 and o.idClient = 1 and o.idSubClient = -1
   UNION ALL
   select elem.idUser, elem.root, o.idElement, o.idParent, o.idSport, o.active
   from elem 
   join organigram o on o.idElement = elem.idParent
)
select idElement, idParent, active,idsport, root
from elem          
group by idelement
 

У меня есть организационная диаграмма, в которой я могу назначить пользователя нескольким элементам организационной диаграммы. В зависимости от элемента, которому он назначен, я хотел бы проверить всех родителей, если столбец «активный» равен 1 или 0. Если один из элементов parnet имеет active = 0, то он ничего не возвращает.

В этом случае пользователь назначается элементам 4 и 7. Запрос должен показать мне только родительские элементы элемента 7, потому что родительский элемент элемента 4 активен = 0

Ожидаемый результат (поскольку третий элемент имеет active = 0): 1 5 6 7

Но результат таков: 1 2 3 4 5 6 7

SQL скрипка

Я проверил свой рекурсивный запрос здесь с помощью MariaDB

Ответ №1:

Я думаю, что вам нужно:

 with recursive elem as (
   select elem.idUser, elem.idElement as root, o.idElement, o.idParent, o.idSport, o.active
   from organigram_users elem
   join organigram o on o.idElement = elem.idElement
   where elem.idUser = 50 and o.idClient = 1 and o.idSubClient = -1
   UNION ALL
   select elem.idUser, elem.root, o.idElement, o.idParent, o.idSport, o.active
   from elem 
   join organigram o on o.idElement = elem.idParent
), elements
as (
select idElement, idParent, active,idsport, root
from elem          
group by idelement
)
select * from elements
where not exists (select 'x' from elements where active=false)
 

Комментарии:

1. Я меняю свой вопрос. В моем случае пользователь может быть назначен более чем одному элементу, и мне нужно получить все родительские элементы, пока элемент с idPadren не станет нулевым, но только если все родительские элементы активны = 1

2. Что вы обычно можете сделать в подобном случае, так это добавить запоминаемое значение для всех строк. Поэтому я бы выбрал 2 строковых значения y / n для представления активного / неактивного, а затем объединил их для каждой рекурсии. Итак, для строки привязки, если она активна, y else n как audittrail . Для последовательных строк (объединение всех частей), elem.audittrail (если активный, y else n).

3. В конце каждая строка будет иметь журнал аудита того, откуда она взялась, и все, что вам нужно сделать, это отфильтровать, где audittrail не похож на ‘%n%’. Что здесь немного сбивает с толку, так это то, что вы начинаете с дочерних элементов и находите родителей, в то время как рекурсия обычно идет от более низкой плотности узлов к более высокой. Возможно, дочерние элементы являются родителями в этой конкретной ситуации. В любом случае, как только вы начнете просматривать журнал аудита пути рекурсии, это должно дать вам несколько идей.