0

假设我们有 3 个名为TRANSACTIONS,的表ORDERSPAYMENTS它们都有TRANSACTION_ID.

这是我加入有 5 个订单和 3 个付款的交易时得到的常规输出:

transaction_id, order_id, payment_id
----------
1, 20, 35
1, 20, 36
1, 20, 37
1, 21, 35
1, 21, 36
1, 21, 37
....

我应该得到的是:

transaction_id, order_id, payment_id
----------
1, 20, 35
1, 21, 36
1, 22, 37
1, 23, null
1, 24, null

如果付款多于订单,则应NULLorder_id列中。

基本上我需要每行数transaction_id等于orders/的更大数量payments(在这个例子中5> 3所以5)。

请记住,这些表中的每一个都有几百万条记录。

编辑

根据评论中的请求,上面的查询是简单的连接

SELECT t.transaction_id, o.order_id, p.payment_id
FROM TRANSACTION t
LEFT JOIN ORDERS o on o.transaction_id = t.transaction_id
LEFT JOIN PAYMENTS p on p.transaction_id = o.transaction_id

编辑 2

我不能透露全表方案,我只写了查询工作所必需的列。实际上,这些表中的每一个都有 20 多列,并且查询应该返回总共大约 20 列。同样,TRANSACTIONS有超过 1 亿条记录,并且两者ORDERS都有15 亿多PAYMENTS条记录,我们需要返回大约 10 万条记录。

4

2 回答 2

1

在这种情况下,您应该向and表添加一个额外的 RowNumber 列(使用ROW_NUMBER() OVER),然后将它们与该列连接。OrdersPayments

SQLFiddle 演示

select tr.transaction_id, 
       Orders.order_id,
       Payments.payment_id

from TRANSACTIONS tr

LEFT JOIN 
(
select transaction_id,order_id,
       ROW_NUMBER() 
       OVER (PARTITION BY transaction_id ORDER BY order_id) as rn
FROM ORDERS
) Orders on tr.transaction_id=Orders.transaction_id

LEFT JOIN 
(
select transaction_id,payment_id,
       ROW_NUMBER() 
       OVER (PARTITION BY transaction_id ORDER BY payment_id) as rn
FROM PAYMENTS
) Payments on (tr.transaction_id=Payments.transaction_id)
                  AND (Orders.rn=Payments.rn)

UNION 

select tr.transaction_id, 
       Orders.order_id,
       Payments.payment_id

from TRANSACTIONS tr

LEFT JOIN 
(
select transaction_id,payment_id,
       ROW_NUMBER() 
       OVER (PARTITION BY transaction_id ORDER BY payment_id) as rn
FROM PAYMENTS
) Payments on (tr.transaction_id=Payments.transaction_id)

LEFT JOIN 
(
select transaction_id,order_id,
       ROW_NUMBER() 
       OVER (PARTITION BY transaction_id ORDER BY order_id) as rn
FROM ORDERS
) Orders on tr.transaction_id=Orders.transaction_id
            AND (Orders.rn=Payments.rn)

另一种方法是没有联合。在这种情况下,我们需要生成序列 1,2,3,4....,然后将两个表也加入到这个序列中。在这个例子中,我们生成从 1 到 1000 ( CONNECT BY LEVEL <= 1000) 的序列。如果您不知道可能的最大行数是多少,那么您可以使用select COUNT() ...从两个表中生成的序列作为序列生成器的最大数量。

SQLFiddle 演示

select tr.transaction_id, 
       Orders.order_id,
       Payments.payment_id

from TRANSACTIONS tr
CROSS JOIN
(SELECT LEVEL as rn
FROM dual
CONNECT BY LEVEL <= 1000
) Cnt  

LEFT JOIN 
(
select transaction_id,order_id,
       ROW_NUMBER() 
       OVER (PARTITION BY transaction_id ORDER BY order_id) as rn
FROM ORDERS
) Orders on (tr.transaction_id=Orders.transaction_id)
            AND 
            (cnt.rn=Orders.rn )

LEFT JOIN 
(
select transaction_id,payment_id,
       ROW_NUMBER() 
       OVER (PARTITION BY transaction_id ORDER BY payment_id) as rn
FROM PAYMENTS
) Payments on (tr.transaction_id=Payments.transaction_id)
            AND 
            (cnt.rn=Payments.rn)

WHERE Payments.payment_id IS NOT NULL or 
      Orders.Order_id IS NOT NULL 
order by tr.transaction_id,cnt.rn
于 2013-11-15T11:20:16.943 回答
1

您应该合并两个结果并检查它的行,如下所示:

select transaction_id, sum(order_id) as order_id, sum(payment_id) as payment_id
from
(
    SELECT t.transaction_id, 
           ROW_NUMBER() OVER (PARTITION BY t.transaction_id ORDER BY order_id) RowNo, 
           o.order_id, 
           null as payment_id
    FROM TRANSACTIONS t
    LEFT JOIN ORDERS o on o.transaction_id = t.transaction_id

    union 

    SELECT t.transaction_id, 
           ROW_NUMBER() OVER (PARTITION BY t.transaction_id ORDER BY payment_id) RowNo, 
           null as order_id, 
           p.payment_id
    FROM TRANSACTIONS t
    LEFT JOIN Payments p on p.transaction_id = t.transaction_id
) tt
group by transaction_id, RowNo

SQL 小提琴演示:http ://sqlfiddle.com/#!3/e991d/21

更新 :

请尝试使用 JOIN 而不是 UNION ,如下所示:

SELECT t1.transaction_id, t1.order_id, t2.payment_id
from   
(
  SELECT t.transaction_id, 
         ROW_NUMBER() OVER (PARTITION BY t.transaction_id ORDER BY order_id) RowNo,
         o.order_id
  FROM TRANSACTIONS t
  LEFT JOIN ORDERS o on o.transaction_id = t.transaction_id
) t1
full join 
(
  SELECT t.transaction_id, 
         ROW_NUMBER() OVER (PARTITION BY t.transaction_id ORDER BY p.payment_id) RowNo,
         p.payment_id
  FROM TRANSACTIONS t
  LEFT JOIN Payments p on p.transaction_id = t.transaction_id
  ) t2
on t1.transaction_id = t2.transaction_id and t1.RowNo = t2.RowNo

SQL 小提琴演示:http ://sqlfiddle.com/#!3/e991d/20

于 2013-11-15T11:43:28.410 回答