2010-03-11 72 views
5

我們已經建立了一個表,如下所示:是否有針對此問題的基於集合的解決方案?

|ID|EmployeeID|Date  |Category  |Hours| 
|1 |1   |1/1/2010 |Vacation Earned|2.0 | 
|2 |2   |2/12/2010|Vacation Earned|3.0 | 
|3 |1   |2/4/2010 |Vacation Used |1.0 | 
|4 |2   |5/18/2010|Vacation Earned|2.0 | 
|5 |2   |7/23/2010|Vacation Used |4.0 | 

的業務規則:

  • 度假平衡被用來度假賺減去假期計算。
  • 使用的假期總是首先應用於最早的假期收入金額。

我們需要返回休假期間沒有被假期使用的假期抵消的行。如果使用的假期只抵消了度假收入記錄的一部分,我們需要返回顯示差異的記錄。例如,使用上表中,結果集看起來像:

|ID|EmployeeID|Date  |Category  |Hours| 
|1 |1   |1/1/2010 |Vacation Earned|1.0 | 
|4 |2   |5/18/2010|Vacation Earned|1.0 | 

注意記錄2被淘汰,因爲它完全被使用的時間偏移,但記錄1和4只部分使用,所以他們計算並返回。

我們唯一想到這樣做的方法是將所有度假收入記錄都放到臨時表中。然後,獲取所使用的總假期並循環訪問臨時表,刪除最舊的記錄並從總假期中扣除該值,直到總假期使用爲零。我們可以清理它,因爲剩餘的假期只是最古老的假期收入記錄的一部分。這隻會讓我們獲得傑出的度假收入紀錄。

這可行,但效率非常低,表現不佳。此外,隨着越來越多的記錄被添加,性能將隨着時間的推移而降低。

有沒有更好的解決方案的建議,最好是基於集?如果沒有,我們只需要去解決這個問題。

編輯:這是一個供應商數據庫。我們不能以任何方式修改表格結構。

回答

2

下應該這樣做..

(但別人提,最好的解決辦法是,因爲他們花了調整剩餘的假期..)

select 
    id, employeeid, date, category, 
    case 
    when earned_so_far + hours - total_spent > hours then 
     hours 
    else 
     earned_so_far + hours - total_spent 
    end as hours 
from 
    (
       select 
        id, employeeid, date, category, hours, 
        (
         select 
          isnull(sum(hours),0) 
         from 
          vacations 
         WHERE 
          category = 'Vacation Earned' 
          and 
          date < v.date 
          and 
          employeeid = v.employeeid 
        ) as earned_so_far, 
        (
         select 
          isnull(sum(hours),0) 
         from 
          vacations 
         where 
          category = 'Vacation Used' 
          and 
          employeeid = v.employeeid 
        ) as total_spent 
       from 
        vacations V 
       where category = 'Vacation Earned' 
    ) earned 
where 
    earned_so_far + hours > total_spent 

的邏輯是

  1. 計算每個earned一行,所賺的小時數目前爲止
  2. 計算用於該用戶
  3. 的總小時數選擇該記錄,如果total_hours_so_far +小時此記錄的 - 我應該提到這total_spent_hours> 0
+0

和'課程類別不應該是文本,但從另一個表中的一些ID .. – 2010-03-11 19:31:14

+0

這是,我只是在文本中努力使問題更清楚。 – NYSystemsAnalyst 2010-03-11 20:01:07

+1

+1我試着解決這個問題,我的解決方案非常接近這個問題,所以不值得發佈。我認爲這是正確的做法。 – 2010-03-11 21:01:19

0

隨着時間的推移和添加記錄,除非你做一些事情,比如性能將會得到越來越糟糕:

  • 清除舊行一旦他們「抵消」(例如假期賺了有相同的度假使用的行添加和佔;假期使用已被使用設置「過期」假期賺「消費」)
  • 添加一列標誌,如果行被「取消」,並將此列納入您的索引

跟蹤以這種方式進行的數據更改似乎是修改表格結構的參數(有幾個,而不僅僅是一個),但這超出了當前問題的範圍。

至於查詢本身,我會建立兩個聚合,做一些減法,做一個子查詢,然後加入它的巧妙使用的一個排名函數。聞起來就像在某處也有相關的子查詢。我可能會試着在以後散列(我時間很短),但我敢打賭有人會打我。

+0

是一個供應商數據庫(見上文編輯)。因此,不可能修改表格。 – NYSystemsAnalyst 2010-03-11 19:59:54

2

在考慮這個問題時,我想到在休假時需要關心的唯一原因是它是否過期。如果是這樣的話,最簡單的解決方案是將「假期過期」記錄添加到表中,這樣員工的剩餘假期總是隻有sum(vacation earned) - (sum(vacation expired) + sum(vacatation used))。您甚至可以使用上次休假過期記錄作爲查詢的起點,顯示您想要的確切記錄。

但我猜這不是一個選項。要解決問題,請記住,每當您發現自己使用臨時表時,請嘗試將該數據放入CTE(公用表表達式)中。不幸的是,我現在有一個會議,所以我沒有時間寫查詢(也許以後,這聽起來很有趣),但這應該讓你開始。

0

我建議修改表以跟蹤其自身列中的餘額。這樣,您只需抓取最新的記錄即可瞭解員工的職位。

這樣,你就可以滿足簡單的情況(「我有多少假期」),同時仍然可以做你想要的尷尬總結在你的「休假時間哪些位不要排隊與其他位「報告,我希望是你不經常需要的東西。

+0

我應該提到這是一個供應商數據庫(見上面的編輯)。因此,不可能修改表格。 – NYSystemsAnalyst 2010-03-11 20:00:28

1

我發現你的整個結果集令人困惑和不準確,我可以看到員工說:「不,我在1月25日2小時不賺1。」如果他們選擇以這種方式進行展示,那麼他們在當天只能獲得1小時的部分抵消並不是真的,並且你將不會遇到任何問題。我會用不同的方式來呈現信息。通常,您可以在底部顯示所有請假行爲(已獲得,已過期和已使用)的列表,或者提供可供使用和使用的摘要。

在過去30多年的員工隊伍中,我經歷了許多不同的計時系統(以及在我擔任管理分析師時研究得更多),我從未見過任何人想要以這種方式顯示計時信息。我在想這是有原因的。如果這是一項要求,我會建議重新推行,並解釋如何讀取數據以及如何難以獲得性能良好的解決方案。如果不試圖說服客戶這是一個糟糕的主意,我不會接受這一要求。

+0

這是一個供應商數據庫,我無法控制數據的結構。此結果集不會顯示給大多數用戶。一些管理者想知道一個人剩下的假期時間以及獲得時間的確切日期。 – NYSystemsAnalyst 2010-03-11 19:56:24

相關問題