查询两个相似的表并组合排序的结果

时间:2015-01-14 15:54:16

标签: sql postgresql union

我有三张桌子

orders.orderid (and other non-pertinent stuff)

payment.orderid
payment.transactiondate
payment.amount

projectedpayment.orderid
projectedpayment.projecteddate
projectedpayment.projectedamount

基本上,payment代表收到实际付款的时间; projectedpayment表示系统认为应该接收它们的时间。我需要构建一个查询来比较投影与实际。

我想查询它们,以便查询中的每一行都有orderid,payment.transactiondate,payment.amount,projectedpayment.projecteddate,projectedpayment.projectedamount,其中来自payment和projectedpayment的行按其各自排序日期。如,

orderid transactiondate amount projecteddate projectedamount
      1      2015-01-01  12.34    2015-01-03           12.34
      1      2015-01-15  12.34    2015-01-15           12.44
      1            null   null    2015-02-01           12.34
      2      2014-12-31  50.00          null            null

按订单细分,实际和预计付款是多少,预计付款可能比实际付款多,或实际付款多于预计付款,按日期排列(简单地按两种方式排序,没有比这更复杂) 。

似乎我应该能够使用left joinordersunion的其他两个表的order by来实现这一目标,但是我还没有能够使它发挥作用,所以它可能是完全不同的东西。我知道我无法加入orderpaymentprojectedpayment中的所有三个,或者我得到后两个表的交叉产品。

我碰巧使用postgresql 9.4,但希望我们不需要过于特定于数据库。

3 个答案:

答案 0 :(得分:2)

我不知道postgres抱歉:(但如果你知道怎么做分区行数这样的事情应该有效。

select
    coalesce(a.orderid,b.orderid) as orderid
    ,transactiondate
    ,amount
    ,projecteddate
    ,projectedamount
FROM

        (select
            orderid
            ,ransactiondate
            ,amount
            ,row_number() over (partition by orderid order by orderid,transactiondate) as rn
        from payment) as a

        full join 
        (select
            orderid
            ,projecteddate
            ,projectedamount
            ,row_number() over (partition by orderid order by orderid,projecteddate) as rn
        from projectedpayment) as b

        on a.orderid= b.orderid
        and a.rn = b.rn

*这是sqlserver语法(2K5 + AFAIK)

这里的逻辑是您需要为每个预测付款和实际付款分配一个唯一的编号,以便您可以将两个表连接在一起,但每行只匹配另一个表中的一行。

如果您每天只有一次付款,那么您可以在订单ID和日期上完全加入,而不必担心行号。

完整连接允许您在任何一方都有空值,因此您需要合并orderid

*这也不显示没有付款或预测的订单..如果这是一个问题,请评论。

答案 1 :(得分:0)

这应该有效

Select * from Orders o
Left Join Payments p on o.ID = p.OrderID
Left Join ProjectedPaymentp pp on o.ID = pp.OrderID
Order By o.ID

答案 2 :(得分:0)

如果我正确理解,以下查询应该有所帮助:

select o.orderid, ap.transactiondate, ap.amount, pp.projecteddate, pp.projectedamount
from orders o
left join
(
    select p.orderid, p.transactiondate, p.amount,
        row_number() over (partition by p.orderid order by p.transactiondate) n
    from payment p    
) ap on o.orderid = ap.order
left join
(
    select p.orderid, p.projecteddate, p.projectedamount,
        row_number() over (partition by p.orderid order by p.projecteddate) n
    from projectedpayment p  
) pp on o.orderid = ap.order and (ap.n is null or ap.n = pp.n)
order by o.orderid, ap.n, pp.n

<强> UPD 另一种选择(以稍微不同的方式工作,您可以NULL值不仅包含相同orderid的最后记录,而且还会按日期在一个时间轴中完全排序:

select o.orderid, ap.transactiondate, ap.amount, pp.projecteddate, pp.projectedamount
from orders o
inner join
(
    select ap.orderid, ap.transactiondate d from payment ap 
    union   
    select ap.orderid, ap.projecteddate d from projectedpayment pp
) d on d.orderid = o.orderid
left join payment ap on ap.orderid = o.orderid and ap.transactiondate = d.d
left join projectedpayment pp on pp.orderid = o.orderid and pp.projecteddate = d.d
order by o.orderid, d.d