我有三张桌子
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 join
从orders
到union
的其他两个表的order by
来实现这一目标,但是我还没有能够使它发挥作用,所以它可能是完全不同的东西。我知道我无法加入order
,payment
和projectedpayment
中的所有三个,或者我得到后两个表的交叉产品。
我碰巧使用postgresql
9.4,但希望我们不需要过于特定于数据库。
答案 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