簡體   English   中英

sql-query將所有validTo日期更改為下一個validFrom日期減去一天

[英]sql-query that change all validTo dates to the next validFrom date minus one Day

我必須修改一個大的價目表,以便每篇文章只有一個有效的價格。 有時,銷售員工會插入新價格,卻忘記更改舊的無限有效日期。

因此,我必須編寫一個sql查詢以將所有validTo日期更改為下一個有效起始日期減去某一天,即有效日期具有無限有效性(9999-12-31)。 但是我不知道如何僅使用SQL(Oracle 12)達到這一目標。

anr price   validFrom   validTo
1   447.1     2015-06-01  9999-12-31 <
1   447.2       2015-06-16  2015-06-16
1   447.3       2015-06-17  2015-06-17
1   447.4       2015-06-22  2015-06-22
1   447.5       2015-07-06  9999-12-31 <
1   395.0       2015-07-20  2015-07-20
1   447.6       2015-08-03  9999-12-31 <
1   447.7       2015-08-17  9999-12-31 <
1   447.8       2015-08-24  9999-12-31 <
1   395.0       2015-09-07  2015-09-07
1   450.9       2015-11-15  9999-12-31 < no change because it is the last entry

更新表格后,結果應如下所示

anr price   validFrom   validTo
1   447.1       2015-06-01  2015-06-15 <
1   447.2       2015-06-16  2015-06-16
1   447.3       2015-06-17  2015-06-17
1   447.4       2015-06-22  2015-06-22
1   447.5       2015-07-06  2015-07-19 <
1   395.0       2015-07-20  2015-07-20
1   447.6       2015-08-03  2015-08-16 <
1   447.7       2015-08-17  2015-08-23 <
1   447.8       2015-08-24  2015-09-06 <
1   395.0       2015-09-07  2015-09-07
1   450.9       2015-11-15  9999-12-31 <

為了更新結束日期,您只需選擇所有較高開始日期中的最小值即可。

update mytable upd
set enddate = coalesce(
(
  select min(startdate) - 1
  from mytable later
  where later.startdate > upd.startdate
  and later.anr = upd.anr -- same product
), date'9999-12-31') -- coalesce for the case there is no later record
where enddate = date'9999-12-31';

我已將anr作為產品ID。 如果不是,則相應地更改該語句。

Oracle提供了一種分析功能LEAD ,該函數在給定排序標准的情況下引用了當前第n條記錄。 此函數可以用於在更新語句中選擇適當的日期值,如下所示(讓test_prices為表名, ppk為PK):

    update test_prices p
       set p.validTo = (
                        select ps.vtn
                          from (
                                   select lead ( p1.validFrom, 1 ) over ( order by p1.validFrom )  - 1    vtn
                                        , ppk
                                     from test_prices p1
                               ) ps
                         where ps.ppk = p.ppk
                     )
     where to_char(p.validTo, 'YYYY') = '9999'
       and p.validFrom != ( select max(validFrom) from test_prices )
         ;                       
UPDATE VALID_DATES v
SET    validTo = (
  SELECT validTo
  FROM   (
    SELECT anr,
           validFrom,
           COALESCE(
             LEAD( validFrom - 1, 1 ) OVER ( PARTITION BY anr ORDER BY validFrom ),
             validTo
           ) AS validTo
    FROM   valid_dates
  ) u
  WHERE  v.anr       = u.anr
  AND    v.validFrom = u.validFrom
)
WHERE validTo = DATE '9999-12-31';

有兩種可能性:

1.明確的時間跨度

price   validFrom   validTo
90.99   2016-01-01  9999-12-31
80.00   2016-01-16  2016-01-17

第一個價格在1月16日之前和1月17日之后均有效,而第二個價格僅在1月的兩天內有效。

更改第一個validTo將是一個非常糟糕的主意。

2.隱式時間跨度

price   validFrom 
90.99   2016-01-01
80.00   2016-01-16
90.99   2016-01-18

此數據表示與顯式時間跨度示例中的相同。 第一個價格在1月16日之前有效,然后第二個價格在1月17日之前有效,然后第二個價格(再次等於第一個價格)有效。 在這里,您不需要EndDate,因為它是隱式的。 當然 ,第一個價格僅在1月15日之前有效,因為從1月16日起還有另一個價格有效(記錄2)。

因此:完全刪除EndDate列,或使其保持不變。 不要像您打算的那樣簡單地對其進行更新。 如果將記錄更新為下一個日期減去一個記錄,則實際上將多余地保存數據,這可能會在以后導致問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM