2013-10-03 126 views
0

我目前正在進行工資發放。我已經設法在同一天計算出入職和退休員工的小時數。以下是我正在提取的記錄的樣本表。我的問題是,如果員工在晚上10點到早上6點的班次或類似的班次工作,要求他們在第二天工作,我無法弄清楚使用什麼條件。 Im在我的查詢中使用distinct,因爲hr提供的數據包含許多重複條目。從特定日期獲得記錄

---------------------------------------------------- 
| empID  | Date  | Type | RecTime | 
---------------------------------------------------- 
| 1  | 2012-11-01 | 1-TIME IN | 21:45 | 
| 1  | 2012-11-02 | 1-TIME OUT | 06:05 | 
| 1  | 2012-11-02 | 1-TIME IN | 21:33 | 
| 1  | 2012-11-03 | 1-TIME OUT | 06:08 | 
| 1  | 2012-11-04 | 1-TIME IN | 11:49 | 
| 1  | 2012-11-04 | 1-TIME OUT | 21:39 | 
| 1  | 2012-11-05 | 1-TIME IN | 14:25 | 
| 1  | 2012-11-05 | 1-TIME OUT | 20:07 | 
---------------------------------------------------- 

這是我的PHP代碼:

<?php 

$c = 1; 
$query = mysql_query("SELECT DISTINCT EmpID, Date, Type from paymaster2c.tx_tito_pm ORDER BY EmpID, Date"); 
while ($row = mysql_fetch_array($query)){ 
$EID = $row['EmpID']; 
$D = $row['Date']; 
$T = $row['Type']; 

$RTi = 'no time in'; 
$RTo = 'no time out'; 
$RBo = 'no break out'; 
$RBi = 'no break in'; 

$query1 = mysql_query("SELECT RecTime from tx_tito_pm WHERE Date='$D' AND EmpID='$EID' AND Type='1-TIME IN' LIMIT 1"); 
while ($row1 = mysql_fetch_array($query1)){ 
$RTi = date('H:i:s',strtotime($row1['RecTime'])); 

    if (date('H:i:s',strtotime('$RTi')) > date('H:i:s',strtotime('03:00 PM')) && date('H:i:s',strtotime('$RTi')) <= date('H:i:s',strtotime('11:59 PM'))) { 
    $date = new DateTime('$D'); 
     $date->add(new DateInterval('P1D')); 
     $NewDate = $date->format('Y-m-d'); 

     //$NewD = date('Y-m-d', strtotime('$D + 1day')); 
     $query3 = mysql_query("SELECT RecTime from tx_tito_pm WHERE Date='$date' AND EmpID='$EID' AND Type='4-TIME OUT' LIMIT 1"); 
      while ($row3 = mysql_fetch_array($query3)){ 
       $RTo = date('H:i:s',strtotime($row3['RecTime'])); 

       $RTii = date('H:i:s',strtotime('23:59:00')) - date('H:i:s',strtotime($RTi)); 

      $start_date = new DateTime(date('H:i:s',strtotime('23:59:00'))); 
      $since_start = $start_date->diff(new DateTime(date('H:i:s',strtotime('$RTi')))); 
      $start_date1 = new DateTime(date('H:i:s',strtotime('00:00:00'))); 
      $since_start1 = $start_date1->diff(new DateTime(date('H:i:s',strtotime('$RTo')))); 

      $M1 = $since_start1->i ; 
      $H1 = $since_start1->h ; 
      $M = $since_start->i ; 
      $H = $since_start->h ; 
      $a = $H + $H1; 
      $b = $M + $M1; 


      $RTD = $RTo-$RTi; 

      echo "#" .$c. " ". $EID . " == " . $D . " == " . date('D', strtotime($D)) ." == " . $T ." ==>>" .$RTo. "-". $RTi. "==" .$RTD. "//" .$a. "hrs and " .$b. "minutes. <br /> \n"; 
      $c++; 
      } 

    } 
    else { 

    $query2 = mysql_query("SELECT RecTime from tx_tito_pm WHERE Date='$D' AND EmpID='$EID' AND Type='4-TIME OUT' LIMIT 1"); 
     while ($row2 = mysql_fetch_array($query2)){ 
     $RTo = date('H:i:s',strtotime($row2['RecTime'])); 

      $start_date = new DateTime(date('H:i:s',strtotime($RTo))); 
      $since_start = $start_date->diff(new DateTime(date('H:i:s',strtotime($RTi)))); 

      $M = $since_start->i ; 
      $H = $since_start->h ; 


      $RTD = $RTo-$RTi; 

      echo "#" .$c. " ". $EID . " == " . $D . " == " . date('D', strtotime($D)) ." == " . $T ." ==>>" .$RTo. "-". $RTi. "==" .$RTD. "//" .$H. "hrs and " .$M. "minutes. <br /> \n"; 
      $c++; 

     } 
    } 
} 


} 
echo $c; 
?> 

希望有人能幫助我。非常感謝你提前。

+0

請不要使用'mysql_ *',它已經過時並且不安全。閱讀關於PDO和MySQLi。 –

+0

您需要維護表級別的額外信息。需要保持每個員工工作的轉變,每個班次的開始和結束時間。您不應該使用DISTINCT,因爲員工可能會在班次中多次進入和退出。有了這些信息,你應該能夠滿足要求。 – rags

+1

@FranciscoPresencia,我現在還在嘗試學習PDO和MySQLi。仍然在學習,但是,儘管如此。:) – user2842120

回答

0

我認爲你需要最終開發新的或額外的表來幫助你解決這個問題(如果你想追求一個以MySQL爲中心的解決方案)。下面是一個強力的查詢,可能需要優化/個性化,包括:

  • 確保您有所需的字段的索引
  • (恕我直言)創建SQL視圖來封裝這些派生表(即在括號內重複選擇)
  • 我不知道你的字段類型。所以我認爲時間是一個字符場。這可能需要更改
  • 您可能希望運行此查詢的變體來填充臨時表或工作表。隨着數據集的增長,確定輪班結束的自加入將變得密集
  • 最後,當數據具有不匹配/配對的值時(例如,沒有結帳的兩個簽入 - 反之亦然) 。)

對於演示看到:http://sqlfiddle.com/#!2/558fb/22

樣本輸出

| EMPID |       CHECKIN |      CHECKOUT | WORKED | 
|-------|---------------------------------|---------------------------------|--------| 
|  1 | November, 01 2012 21:45:00+0000 | November, 02 2012 06:05:00+0000 | 8.3333 | 
|  1 | November, 02 2012 21:33:00+0000 | November, 03 2012 06:08:00+0000 | 8.5833 | 
|  1 | November, 04 2012 11:49:00+0000 | November, 04 2012 21:39:00+0000 | 9.8333 | 
|  1 | November, 05 2012 14:25:00+0000 | November, 05 2012 20:07:00+0000 | 5.7 | 

SQL代碼:

SELECT TimeIn.empID, TimeIn.BetterDate AS CheckIn, TimeOut.BetterDate AS CheckOut 
, (TO_SECONDS(TimeOut.BetterDate) - TO_SECONDS(TimeIn.BetterDate))/(60*60) AS Worked 
FROM (
SELECT empID, Type, Date, RecTime, DATE_ADD(Date, Interval RecTime HOUR_MINUTE) as BetterDate 
FROM timedata) AS TimeIn 
LEFT JOIN (
    SELECT empID, Type, Date, RecTime, DATE_ADD(Date, Interval RecTime HOUR_MINUTE) as BetterDate 
    FROM timedata) AS TimeOut 
ON TimeIn.EmpID = TimeOut.EmpID 
    AND TimeIn.BetterDate < TimeOut.BetterDate 
    AND TimeOut.Type = '1-TIME OUT' 
    AND NOT EXISTS 
    (SELECT * 
    FROM TimeData 
    WHERE TimeData.Type = '1-TIME OUT' 
     AND DATE_ADD(Date, Interval RecTime HOUR_MINUTE) < TimeOut.BetterDate 
     AND DATE_ADD(Date, Interval RecTime HOUR_MINUTE) > TimeIn.BetterDate) 
WHERE TimeIn.Type = '1-TIME IN' 
ORDER BY CheckIn, CheckOut