3

我有以下数据

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

但这给了我一个循环引用错误(用户数据中的 ORA-01436 CONNECT BY 循环)。添加 nocycle 没有给出正确的集合。

4

2 回答 2

2

此查询仅使用单个全表扫描,如果有索引,则可以使用索引范围扫描。

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;

如果您有大量数据,您将需要彻底测试您使用的任何解决方案。分层查询通常存在严重的性能问题。

于 2011-03-23T04:47:48.823 回答
1
-- 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

可能有更有效的解决方案。

于 2011-03-22T21:50:06.807 回答