我对如何基于日期和sku执行连接感到有点困惑。
我有3个表,其中一个包含订单信息,一个包含订单项,另一个包含费用
我可以加入订单项和订单信息以获取以下内容:
Sku | Price | Date
------ | ------ | -----
ABC1 | 3.99 | 2016-11-01
ABC2 | 2.99 | 2016-10-01
ABC1 | 3.99 | 2016-10-01
ABC3 | 5.99 | 2016-11-01
我需要根据订单日期加入货物的成本
这位于费用表中,如下所示:
Sku | Cost | Valid_from | Valid_to
------ | ------ | ---------- | ----------
ABC1 | 1.99 | 2016-11-01 | NULL
ABC2 | 0.99 | 2015-10-01 | NULL
ABC1 | 2.99 | 2015-10-01 | 2016-10-30
ABC3 | 3.99 | 2015-11-01 | 2016-10-30
某些skus有几个成本记录,有开始和结束日期,其他有一个开始日期,没有结束日期。
我努力查找sku,然后寻找相应的日期
Sku | Price | Date | Cost
------ | ------ | ---------- | -----
ABC1 | 3.99 | 2016-11-01 | 1.99
ABC2 | 2.99 | 2016-10-01 | 0.99
ABC1 | 3.99 | 2016-10-01 | 2.99
ABC3 | 5.99 | 2016-11-01 | 3.99
我可能会尝试过它,但似乎无法加入这些并获取相关信息。
任何有用的帮助
答案 0 :(得分:2)
您可以动态创建日期范围,然后测试订单项中的日期是否属于该范围:
select li.*, c.cost
from line_item li
join cost c on li.sku = c.sku
and li.date <@ daterange(c.valid_from, c.valid_to);
使用NULL
作为范围的上限会自动使其成为无限范围,因此无需在查询中明确处理NULL
。
在线示例:http://rextester.com/OAJ69387
日期范围内的索引可能会加快速度:
create index on cost using gist (daterange(valid_from, valid_to));
注意:
对于您的示例数据,上述查询将不返回包含SKU ABC3的订单项的费用信息,因为该订单项的日期不属于费用行定义的范围ABC3。如果您的样本数据是正确的,并且您确实需要包含订单项ABC3,则需要外部联接 - 但是您不会有成本价值。
答案 1 :(得分:0)
您需要在范围内的日期。但在这种情况下,您需要两个条件来处理开放范围。
SELECT io.*, c.Cost
FROM itemOrder io
JOIN costs c
ON io.Sku = c.Sku
AND ( (io.Date >= c.Valid_from and c.Valid_to IS NULL)
OR (io.Date >= c.Valid_from and io.Date <= c.Valid_to)
) -- ^^ this may need to be `<`
-- depend on how you define your ranges
答案 2 :(得分:0)
Valid_To列显然是多余的,我强烈建议将其从表中删除。
要获取订单日期的最新价格,请使用交叉申请前1个查询:
select o.sku, o.price, o.date, cx.cost
from order o
cross join lateral
(
select cost
from costs c
where c.sku = o.sku and c.valid_from <= o.date
order by date desc
limit 1
) cx;