2016-11-04 78 views
1

我對如何執行基於日期和sku的連接有點難住。SQL加入ID和日期

我有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 

我可能嘗試過工程師,但似乎無法得到接近加盟這些並取回相關信息。

任何幫助appriciated

+0

對於SKU行項目'ABC3'沒有相應的成本項(2016年11月1日之後是ABC3的成本範圍的結束)。因此,無論您的預期輸出是錯誤的還是樣本數據。 –

回答

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)); 

注:

爲了您的樣本數據,上面的查詢將不是返回成本信息由於該行項目的日期不屬於ABC3的成本行定義的範圍,因此需要使用SKU ABC3對行項目進行定價。如果您的示例數據是正確的,並且您確實希望包含訂單項ABC3,則需要外部聯合 - 但您不需要成本值。

+0

尋找日期範圍教程索引應該看起來像CREATE INDEX cars_price_range_idx ON汽車使用要點(成本); '和你寫的一樣嗎?看起來在'cost'列上創建一個'GIST'索引就足夠了 –

+0

@JuanCarlosOropeza:'cost'列的索引是完全沒有用的。但你是對的,它應該是一個主要指標。 –

+0

對不起,我的意思是日期欄。我看到的例子是在一些範圍之間的成本,並且該指數在成本列中。我認爲現在會創建一個'範圍'索引。 –

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 
+0

基本上應該是馬回答相同的結果,但他使用'datarange'我不知道。 –

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; 
+0

There在Postgres中不是'交叉應用'。它使用SQL標準的「交叉連接橫向」。我不同意'valid_to'是多餘的:它可以用來創建約束來防止重疊的有效期間 –

+0

@a_horse_with_no_name:哦,謝謝。我將編輯... –

+0

爲什麼你說'valid_to'是多餘的? –