2010-04-05 25 views
2

我正在嘗試編寫一份報告,該報告將在工作時間加入一個人,他們的工作以及他們的小時工資。當日期少於工作日期時,我似乎無法找出加入人員成本的最佳方式。MySQL - 如何內部連接排序加入的數據

比方說,一個人的費用爲每小時$ 30日在今年年初便起身$ 10加註Ø2月5日,另一個在1月

  • 01/01/2010 $ 30.00(每小時)
  • 02/05/2010 $ 40.00
  • 03/01/2010 $ 45.00

的人投入小時數天,這跨越rasies。

  • 01/05/2010 10小時(應爲30 $ /小時)
  • 2010年1月27日5小時(再次在30 $)
  • 2010年2月10日10小時(爲$ 40 /小時)
  • 03/03/2010 5小時(在45 $ /小時)

我想寫一個SQL語句,這將拉動小時,每小時的成本和時間成本*。成本是最後一個進入系統時薪所以成本日期小於工作日期,成本限制日期排序1.

SELECT person.id, person.name, work.hours, person_costs.value, 
     work.hours * person_costs.value AS value 
    FROM person 
    JOIN work ON person.id = work.person_id 
    JOIN person_costs ON person.id = person_costs.person_id 
        AND person_costs.date < work.date 
WHERE person.id = 1234 
ORDER BY work.date ASC 

時遇到的問題,person_costs不被責令日期按降序排列。它會提取與條件相匹配的「任何」值(自然按記錄位置排序)。如何選擇比工作日期早的第一個person_cost值?

謝謝!

回答

0

最好的解決方案是更改person_costs表,以便它記錄日期間隔(開始和結束)的價格,而不是更改後的價格。只要您沒有創建任何重疊的時間間隔,連接就會每個人/日期只獲取一行。

如果您無法更改表格結構,則可以創建實現相同效果的視圖。

+0

此解決方案對我來說效果最好,因爲查詢速度比子查詢(每晚循環播放數百萬條記錄)要快。爲所有邊緣案例構建person_cost的CRUD更加棘手,但這是值得的。 – Gary 2010-04-05 14:26:51

0

這裏是我的測試模式:

Create Table person_cost 
        (
        PersonId int not null 
        , Rate decimal(15,4) not null 
        , [date] datetime not null 
        , Constraint PK_person_cost Primary Key Clustered (PersonId, [date]) 
        ) 
Insert person_cost(PersonId, Rate, [date]) Values(1,30,'2010-01-01') 
Insert person_cost(PersonId, Rate, [date]) Values(1,40,'2010-02-05') 
Insert person_cost(PersonId, Rate, [date]) Values(1,50,'2010-03-01') 

Create Table Work 
       (
       PersonId int not null 
       , [Date] datetime not null 
       , Hours int not null 
       ) 

Insert Work(PersonId, [Date], Hours) Values(1, '2010-01-05', 10) 
Insert Work(PersonId, [Date], Hours) Values(1, '2010-01-27', 5) 
Insert Work(PersonId, [Date], Hours) Values(1, '2010-02-10', 10) 
Insert Work(PersonId, [Date], Hours) Values(1, '2010-03-03', 5) 

而且我的查詢:

Select Work.PersonId, Work.Hours, PayRanges.Rate 
    , Work.Hours * PayRanges.Rate As Value 
From Work 
    Join (
      Select pc1.PersonId, pc1.[date] As StartDate, Rate 
       , Coalesce((Select Min(pc2.[date]) 
        From person_cost As pc2 
        Where pc2.personId = pc1.personId 
         And pc2.[date] > pc1.[date]) 
        , '9999-12-31') As NextEffectiveDate 
      From person_cost As pc1 
      ) As PayRanges 
     On Work.PersonId = PayRanges.PersonId 
      And Work.[Date] >= PayRanges.StartDate 
      And Work.[Date] < PayRanges.NextEffectiveDate 

從本質上說,我計算出的有效工資率的結束日期。在我的例子中,我排除了到Person表的連接,但是可以很容易地將其包含到Person數據中。請注意,我計算付款利率的到期日期將是下一個付款利率生效的日期,因此我查詢的價值嚴格低於到期日期。