2010-11-29 2 views
1

У меня возникли проблемы с написанием SQL-запроса, чтобы найти «цикл» данных в моей таблице Firebird.Firebird SQL Query, чтобы найти цикл в данных

Его очень трудно объяснить ситуацию, поэтому я скорее приведу пример:

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) 
+0

@Delpiguy: ЕСЛИ у вас есть способ, чтобы определить ** простые материалы ** в вашем складе, вы можете быстро проверить с помощью рекурсивного запроса, но не ясно, от того, что вы размещаете если вы иметь способ в своей структуре определить это в запросе, а не из показанной таблицы взрыва. – jachguate 2010-11-29 16:28:51

ответ

1

Я не уверен, о Жар-птице синтаксиса SQL, но это общий SQL Query shold поможет вам:

select * 
from Explosion e1 
inner join Explosion e2 
     on e1.Stockcode = e2.IngredientStockcode 
     and e1.IngredientStockcode = e2.Stockcode 

EDIT

Если бы быстро проверить, и документация, кажется, предполагают, что выше, будет работать. Однако на всякий случай альтернативный синтаксис:

select * 
    from Explosion e1, Explosion e2 
where e1.Stockcode = e2.IngredientStockcode 
    and e1.IngredientStockcode = e2.Stockcode 
+0

Спасибо за ваш быстрый ответ Джеймс, но это не сработает. e1.Stockcode = e2.IngredientStockcode и e2.IngredientStockcode = e1.Stockcode - это точно такое же утверждение. – 2010-11-29 08:42:54

+0

Извините, он запутался. Поменяйте e2 и e1 на последней строке – 2010-11-29 08:49:46

2

У вас типичная проблема с графом/деревом здесь.

Я боюсь, что один запрос не решит вашу проблему. Вам понадобится цикл, чтобы пересечь каждое дерево.

Но у вас есть еще одна проблема, вы не можете легко выбрать корневые узлы. Таким образом, вам нужно будет либо пометить корневые узлы, либо пройти вниз по деревьям вверх (так, начиная с основных ингредиентов, у которых нет дополнительных ингредиентов).

Второй вариант более естественен для данных такого типа, поскольку что-то всегда можно использовать для создания чего-то более сложного.

Вы можете искать google для algoritmes для деревьев в SQL.

Успех