Помощь с подключением по предварительному запросу - PullRequest
3 голосов
/ 22 марта 2011

У меня есть следующие данные

Order_ID  Pallet_ID
O1        P1
O2        P1
O2        P2
O3        P2
O3        P3
O4        P4

Где заказы могут быть на нескольких поддонах, а на поддоне может быть более одного заказа.Мне нужно выбрать группу заказов, которые составляют группу, так как все они имеют одну и ту же группу поддонов.В данных испытаний, приведенных выше, есть две такие группы, {O1, O2, O3} и {O4}, потому что O1, O2 и O3 имеют как минимум один общий поддон с другим членом группы.

Теперь мне нужно немного SQL для этого.Я попытался (где greg_test содержит данные выше)

select distinct order_id
from greg_test
start with order_id = :order_id
connect by pallet_id = prior pallet_id

Но это дало мне ошибку круговой ссылки (цикл CONNECT BY ORA-01436 в пользовательских данных).Добавление ноцикла не дало правильного набора.

Ответы [ 2 ]

2 голосов
/ 23 марта 2011

Этот запрос использует только одно полное сканирование таблицы или может использовать сканирование диапазона индекса, если есть индексы.

select distinct order_id
from greg_test
start with order_id = :order_id
connect by nocycle pallet_id = prior pallet_id or order_id = prior order_id;

Если вы используете 11gR2, он будет работать немного быстрее, чем приведенный выше.по запросу, хотя синтаксис более странный IMO.

with orders(order_id, pallet_id) as
(
    select order_id, pallet_id
    from greg_test
    where order_id = :order_id
    union all
    select greg_test.order_id, greg_test.pallet_id
    from greg_test
    inner join orders
        on greg_test.pallet_id = orders.pallet_id
            or greg_test.pallet_id = orders.pallet_id
) cycle order_id, pallet_id set is_cycle to 'Y' default 'N'
select distinct order_id from orders;

Если у вас есть большие объемы данных, вам необходимо тщательно протестировать любое решение, которое вы используете.Иерархические запросы часто имеют серьезные проблемы с производительностью.

1 голос
/ 23 марта 2011
-- Z lists all order pairs that share a pallet, and also pairs each order with itself
WITH pairs AS (
    -- all pairs of orders on the same pallet
    SELECT DISTINCT a.order_id a, b.order_id b FROM greg_test a, greg_test b 
    WHERE a.pallet_id = b.pallet_id AND a.order_id != b.order_id
  UNION ALL 
    -- pair all orders with themselves
    SELECT DISTINCT order_id a, order_id b FROM greg_test
)
-- Now connect all the pairs
SELECT DISTINCT a FROM pairs 
CONNECT BY NOCYCLE PRIOR a = b 
START WITH a = :order_id

Возможно, есть более эффективное решение.

...