2013-04-25 136 views
4

我正在尋找一些幫助,甚至知道從哪裏開始。本質上,我們有一個爲客戶提供就業開始日期和結束日期的表格。對於年度報告,只要從一個結束日期到下一個開始日期之間的時間不超過21天,就必須計算「連續就業」,其被定義爲最早開始日期到最後結束日期。 這裏是一個例子我的SQL查找跨行日期範圍

employee | Start Date | End Date 
1  | 2012-10-1 | 2012-11-05 
1  | 2012-11-08 | 2013-1-25 
2  | 2012-10-1 | 2012-11-05 
2  | 2012-11-30 | 2013-1-02 
在上述

,我想看到僱員1爲連續地從2012年10月1日採用2013年1月25日 但僱員2將具有2條獨立的就業線表示連續就業2012-10-1至2012-11-05不同於012-11-30至2013-1-02

感謝您的幫助!

回答

3

理論類似於@mellamokb's answer,卻多了幾分簡潔:

SELECT employee, MIN(start) start, end 
FROM (
    SELECT @end:=IF(employee<=>@emp AND @stt<=end+INTERVAL 21 DAY,@end,end) end, 
      @stt:=start start, 
      @emp:=employee AS employee 
    FROM  my_table, (SELECT @emp:=NULL, @stt:=0, @end:=0) init 
    ORDER BY employee, start DESC 
) t 
GROUP BY employee, end 

看到它的sqlfiddle

+0

太棒了!感謝您的答覆!這將是我第一次在select語句中積極使用已定義的變量。這個答案是美麗的代碼:-D – Schugs 2013-04-25 17:08:53

2

在一組記錄中查找「連續組」的一種方法是使用變量來跟蹤每行之間的差異,並開發將連續範圍組合在一起的分組。在下面的例子中,我用三個變量來跟蹤足夠的信息,生成組:

  • @curEmployee - 跟蹤從過往紀錄,當前員工,並與當前記錄的員工相比,我們什麼時候知道的已切換到另一個員工,該員工自動變爲另一個分組
  • @curEndDate - 跟蹤上一條記錄的最後結束日期,因此可以將其與當前記錄的開始日期進行比較,以查看當前記錄是否屬於與之前的記錄相同的「組」 - 也就是說,它是連續工作的一部分,與以前的記錄相同
  • @curGroup - 這是關鍵變量e將行隔離成代表連續工作的獨立「組」。邏輯是,只有滿足以下兩個條件時,才應該將行視爲與前一行連續:兩行具有相同的員工編號,並且前一行的結束日期距離前一行不足21天當前行。
  • 備註:您可能需要驗證邊緣條件,即相隔20/21/22天是否會被視爲連續使用,並調整下面的邏輯。

以下是計算這些組的示例查詢。需要注意以下幾點:變量賦值的順序很重要,因爲它們在select列表中從上到下分配。我們首先需要分配@curGroup,以便它仍然具有來自之前的記錄的@curEmployee@curEndDate的值。其次,order by條款對於確保當我們比較以前和當前記錄時非常重要,它們是彼此最接近的兩條記錄。如果我們以隨機順序查看記錄,它們可能會最終成爲單獨的組。

select 
    e.employee, e.`start date`, e.`end date` 
    ,@curGroup := 
    case when employee = @curEmployee 
     and @curEndDate + INTERVAL 21 DAY >= e.`start date` 
     then @curGroup 
     else @curGroup + 1 
    end as curGroup 
    ,@curEmployee := employee as curEmployee 
    ,@curEndDate := e.`end date` as curEndDate 
from 
    employment e 
JOIN (SELECT @curEmployee := 0, @curEndDate := NULL, @curGroup := 0) r 
order by e.employee, e.`start date` 

示例結果(DEMO) - 注意如何CURGROUP停留在1的前兩行,因爲他們是在彼此的21天,代表連續就業,而最後兩行得到認定爲獨立的組號:

| EMPLOYEE |      START DATE |      END DATE | CURGROUP | CUREMPLOYEE |   CURENDDATE | 
------------------------------------------------------------------------------------------------------------------------------- 
|  1 | October, 01 2012 00:00:00+0000 | November, 05 2012 00:00:00+0000 |  1 |   1 | 2012-11-05 00:00:00 | 
|  1 | November, 08 2012 00:00:00+0000 | January, 25 2013 00:00:00+0000 |  1 |   1 | 2013-01-25 00:00:00 | 
|  2 | October, 01 2012 00:00:00+0000 | November, 05 2012 00:00:00+0000 |  2 |   2 | 2012-11-05 00:00:00 | 
|  2 | November, 30 2012 00:00:00+0000 | January, 02 2013 00:00:00+0000 |  3 |   2 | 2013-01-02 00:00:00 | 

現在我們已經確定的是連續工作的一部分記錄組,我們只需要按這些組號,找到的最小和最大日期範圍輸出:

select 
    employee, 
    min(`start date`) as `start date`, 
    max(`end date`) as `end date` 
from (
    select 
     e.employee, e.`start date`, e.`end date` 
     ,@curGroup := 
     case when employee = @curEmployee 
      and @curEndDate + INTERVAL 21 DAY >= e.`start date` 
      then @curGroup 
      else @curGroup + 1 
     end as curGroup 
     ,@curEmployee := employee as curEmployee 
     ,@curEndDate := e.`end date` as curEndDate 
    from 
     employment e 
    JOIN (SELECT @curEmployee := 0, @curEndDate := NULL, @curGroup := 0) r 
    order by e.employee, e.`start date` 
) as T 
group by curGroup 

示例結果(DEMO):

| EMPLOYEE |      START DATE |      END DATE | 
-------------------------------------------------------------------------------- 
|  1 | October, 01 2012 00:00:00+0000 | January, 25 2013 00:00:00+0000 | 
|  2 | October, 01 2012 00:00:00+0000 | November, 05 2012 00:00:00+0000 | 
|  2 | November, 30 2012 00:00:00+0000 | January, 02 2013 00:00:00+0000 |