2010-03-09 81 views
3

在過去的幾天裏,我一直在用錘子敲着我的桌子,因此我轉向了你,Stack Overflow。在MySQL數據庫中存儲每年可重複的值

我正在使用的軟件具有時間敏感數據。通常的解決方案是有效期限和到期日期。

EFF_DT  XPIR_DT  VALUE 
2000-05-01 2000-10-31 100 
2000-11-01 (null)  90 

這很容易。不幸的是,我們需要在未來任意一年重複的數據。換言之,每個5月1日(2000年開始)我們可能希望有效值爲100,並且每個11月1日我們可能希望將其更改爲90.

這可能是很長時間(> 50年),所以我不想創建一百個記錄。即,我不想這樣做:

EFF_DT  XPIR_DT  VALUE 
2000-05-01 2000-10-31 100 
2000-11-01 2001-04-30 90 
2001-05-01 2001-10-31 100 
2001-11-01 2002-04-30 90 
2002-05-01 2002-10-31 100 
2002-11-01 2003-04-30 90 
... 
2049-05-01 2049-10-31 100 
2049-11-01 2050-04-30 90 
2050-05-01 2050-10-31 100 
2050-11-01 2051-04-30 90 

這些值也可能隨時間而改變。在2000年之前的值可能是恆定的(不倒裝假摔),併爲未來十年值可能最後比的是不同的:

EFF_DT  XPIR_DT  REPEATABLE VALUE 
1995-01-01 2000-04-30 false  85 
2000-05-01 2010-04-30 true  100 
2000-11-01 2010-10-31 true  90 
2010-05-01 (null)  true  120 
2010-11-01 (null)  true  115 

我們已經有一個文本文件(從舊的應用程序),存儲數據的形式非常接近這一點,所以儘可能地遵守這種結構是有好處的。

然後問題出現在檢索中:哪些值適用於今天2010-03-09?

看來最好的辦法是找到每個生效日期(所有活動行)的最新實例,然後看哪個最好。

EFF_DT  MOST_RECENT XPIR_DT  VALUE 
2000-05-01 2009-05-01 2010-04-30 100 
2000-11-01 2009-11-01 2010-10-31 90 

今天的數值爲90,因爲2009-11-01晚於2009-05-01。

,比如說,2007-06-20:

EFF_DT  MOST_RECENT XPIR_DT  VALUE 
2000-05-01 2007-05-01 2010-04-30 100 
2000-11-01 2006-11-01 2010-10-31 90 

值是100,因爲2007-05-01晚於2006-11-01。

使用MySQL日期函數,計算MOST_RECENT字段的最有效方法是什麼?

或者,任何人都可以想出一個更好的方法來做到這一點?

語言是Java,如果它很重要。謝謝大家!

回答

2

假設你想「約會」是「2007-06-20」。

您需要的非重複元素與重複耽誤,所以你可以這樣做(未經測試,可能需要一些thinkering,但應該給你的總體思路):

select * from (
    select * from mytable 
    where 
    repeatable = false 
    and 
    EFF_DT <= '2007-06-20' < XPIR_DT 
    union all 
    select * from mytable 
    where 
    repeatable = true 
    and EFF_DT <= str_to_date(concat("2007", "-", month(EFF_DT), "-", day(EFF_DT)), "%Y-%m-%d") < XPIR_DT 
) 
order by EFF_DT desc limit 1 
+0

謝謝...我會在一些測試數據,並給這個一杆。我會讓你知道結果如何。 :-) – Tenner

+0

我希望能夠在一個數據庫中執行此操作 - 檢索所有數據,數據庫爲我的Java代碼提供一個關於要使用哪一行的「提示」。我認爲我將在底層Java代碼中介紹所有的邏輯。有很多智能我需要放入一個MySQL單線程不能(或不應該)處理。 感謝您的幫助! – Tenner

0

這是一個查詢,您可以使用它來計算數據集的最新EFF_DT。你將不得不在那裏填寫條款,因爲我不知道這些數據是如何組織的。

select EFF_DT form date_table where 1 order by EFF_DT desc limit 1 

的90和100的觸發器是比較複雜的,但你應該能夠使用mysql data and time functions來照顧這。這是一個棘手的問題,我並不是100%地試圖去做。但是,這個查詢檢查XPIR_DT的月份是否大於5月份(第5個月),但是小於11月份(第11個月)。如果這是真的,那麼SQL查詢將返回90,如果假的,那麼你會得到100

select if((month(XPIR_DT)>=5) and (month(XPIR_DT)<11),90,100) from date_table where id=1 
1

我我們不得不通過定期約會&事件來做類似的事情,並且您可能會發現MySQL將會非常開心地使用您不想要的「靜態」日期樣式 - 每個重複實例都有數百行的拼寫。

如果可能的話,我會考慮創建一個單獨的表來存儲它們變平,同時保持有效/到期日期,他們是(以匹配遺留數據&充當父)和1:之間有許多關係這兩個表(即參考原始PK的扁平數據上的「event_id」)。編寫所有這些記錄顯然需要更長時間,但它直接減輕了讀取它們的負擔(通常情況下需要更快)。

創建一個存儲過程或外部程序來處理重新計算平坦的start_date/end_date/value表應該是相當基本的,給定一個常見的時間間隔。查詢數據可能就像WHERE @somedate BETWEEN start_date AND end_date一樣簡單,而不是越來越複雜的轉換&日期數學。

同樣,插入和更新將會更慢,但「數百行」甚至沒有抓住MySQL的能力。如果只有兩個日期,一個int和某種int鍵,那麼在子面向服務器上寫幾百條記錄不應該花費幾秒鐘。如果我們正在談論數百萬條記錄,那麼也許可以調整一些東西(你是否真的需要跟蹤50年前或者只是下一個5?可以通過cron重新計算到非高峯時間等等),但即使如此,MySQL也只是比每次計算差異要有效得多。

另外的可能感興趣的:What's the best way to model recurring events in a calendar application? & Data structure for storing recurring events?

+0

感謝您的輸入。我猶豫擴大數據的原因之一是可能需要編輯這些循環數據點。也就是說,如果價值從90變到95,我想在一個地方改變它,而不是一百個。而且,用戶界面需要能夠將這些數據「摺疊」成合理的形式。 (用戶應該看到兩排,而不是100)。然而,在這裏好吃的食物...... – Tenner