Firebird SQL Query для поиска петли в данных
У меня проблемы с написанием SQL-запроса, чтобы найти "цикл данных" в моей таблице Firebird.
Очень сложно объяснить ситуацию, поэтому я приведу пример:
Table: Explosion
Stockcode | IngredientStockcode
----------------------------------
001 | 010
001 | 011
001 | 012
010 | 011
010 | 013
010 | 014
012 | 013
012 | 015
012 | 001 <-- This causes a loop in my data. Stockcode 001 has an
ingredient of 012 and stockcode 012 has 001 as
an ingredient.
013 | 014
013 | 015
013 | 001 <-- This also causes a loop in my data. 013 is part of (an
ingredient of) 010. 010 is also an ingredient of 001. 001
cannot then also be an ingredient of 013.
Мне нужно написать запрос, чтобы определить эти "петли" в данных. Любая помощь будет оценена.
Это должен быть сложный запрос с объединениями. Я уже пробовал что-то подобное ниже, и я думаю, что я на правильном пути..
select * FROM explosion x1
WHERE EXISTS ( SELECT 1 FROM Explosion x2
where exists ( SELECT 1 FROM Explosion x3 where
x3.ingredientStockcode = x1.Stockcode
AND x1.RDB$DB_KEY < x3.RDB$DB_KEY)
and x1.ingredientStockcode = x2.Stockcode
AND x1.RDB$DB_KEY < x2.RDB$DB_KEY)
2 ответа
Здесь у вас типичная проблема с графиком / деревом.
Боюсь, что один запрос не решит вашу проблему. Вам понадобится цикл, чтобы пройти каждое дерево.
Но у вас есть другая проблема, вы не можете легко выбрать корневые узлы. Таким образом, вам нужно будет либо разметить корневые узлы, либо пройтись по деревьям снизу вверх (начиная с базовых ингредиентов, которые не имеют дополнительных ингредиентов).
Второй вариант более естествен для такого рода данных, потому что что-то всегда пригодно для создания чего-то более сложного.
Вы можете искать в Google алгоритмы для деревьев в SQL.
успех
Я не уверен насчет синтаксиса Firebird SQL, но этот общий запрос SQL поможет вам:
select *
from Explosion e1
inner join Explosion e2
on e1.Stockcode = e2.IngredientStockcode
and e1.IngredientStockcode = e2.Stockcode
РЕДАКТИРОВАТЬ
Была быстрая проверка, и документация, кажется, предполагает, что вышеупомянутое будет работать. Однако, на всякий случай, альтернативный синтаксис:
select *
from Explosion e1, Explosion e2
where e1.Stockcode = e2.IngredientStockcode
and e1.IngredientStockcode = e2.Stockcode