2017-09-22 32 views
0

我有一個tableidemployee_iddevice_idlogged_time[簡化]該記錄來自生物測定設備的員工出勤。 我生成報告,顯示每個員工按日期分配的首次和最後一次出廠時間。對應於最大/另一列的無分鐘選擇列(多個)連接

目前,我能夠按日期取得每位員工的首次進入時間,但我也需要取得每位員工的第一次進入和最後一次進入device_id。條目不按記錄時間的順序排列。

我不希望(也可能不能)使用連接,因爲在其中一個報告中列動態生成,並可能導致數千個連接。此外,這些是子查詢,並加入到其他查詢以獲得更多詳細信息。

表中的樣品的設置和查詢是在http://sqlfiddle.com/#!9/3bc755/4

第一個只是顯示列出了每個員工

select 
    attendance_logs.employee_id, 
    DATE(attendance_logs.logged_time) as date, 
    TIME(MIN(attendance_logs.logged_time)) as entry_time, 
    TIME(MAX(attendance_logs.logged_time)) as exit_time 
from attendance_logs 
group by date, attendance_logs.employee_id 

的日期的入口和出口時間的第二個構建了出勤圖表給定日期範圍

select 
    `attendance_logs`.`employee_id`, 

    DATE(MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-18' THEN `attendance_logs`.`logged_time` END)) as date_2017_09_18, 
    MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-18' THEN `attendance_logs`.`logged_time` END) as entry_2017_09_18, 
    MAX(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-18' THEN `attendance_logs`.`logged_time` END) as exit_2017_09_18, 

    DATE(MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-19' THEN `attendance_logs`.`logged_time` END)) as date_2017_09_19, 
    MIN(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-19' THEN `attendance_logs`.`logged_time` END) as entry_2017_09_19, 
    MAX(case when DATE(`attendance_logs`.`logged_time`) = '2017-09-19' THEN `attendance_logs`.`logged_time` END) as exit_2017_09_19 

    /* 
    * dynamically generated columns for dates in date range 
    */ 
from `attendance_logs` 
where `attendance_logs`.`logged_time` >= '2017-09-18 00:00:00' and `attendance_logs`.`logged_time` <= '2017-09-19 23:59:59' 
group by `attendance_logs`.`employee_id`; 

嘗試:

類似於每個日期的最大和最小logged_time使用case,試圖選擇device_id其中logged_time是最大/最小值。

```MIN(case 
    when 
    `attendance_logs.logged_time` = MIN(
     case when DATE(`attendance_logs`.`logged_time`) 
     = '2017-09-18' THEN `attendance_logs`.`logged_time` END 
    ) 
then `attendance_logs`.`device_id` end) as entry_device_2017_09_18 ``` 

這導致invalid use of group by

+0

特定於日期的動態列的任何原因?看起來非常「不相關」...... –

+0

@RomanSusi,基本上,查詢的結果是「生成的報告」(有一些變化),這也用於多個功能相似但功能不同的地方。 在整個月或幾個月內爲每位員工提取每日出勤數據,並在應用程序端處理此圖表(包括有關班次,日程安排等的額外計算)可能會變得複雜並且會隨時間和內存出現問題,因爲數據巨大。在數據庫上這樣做似乎很好。 建議更好的方式將不勝感激。 – Shuvo

回答

0

快速破解您的查詢使用GROUP_CONCAT與接設備ID的進出在SUBSTRING_INDEX

SUBSTRING_INDEX(GROUP_CONCAT(case when DATE(`l`.`logged_time`) = '2017-09-18' THEN `l`.`device_id` END ORDER BY `l`.`device_id` desc),',',1) exit_device_2017_09_18, 

或者,如果設備ID將是相同的對於每個輸入和輸出,只要它可以寫成GROUP_CONCAT只有

GROUP_CONCAT(DISTINCT case when DATE(`l`.`logged_time`) = '2017-09-18' THEN `l`.`device_id` END) 

DEMO

+0

不會通過'logged_time'而不是'device_id'排序嗎?並且不會有'device_id'的入口和出口不同。 我很感興趣這將如何擴展?可能有100個列和數千行。 – Shuvo

+0

不,它將用於訂購device_id,logged_time不能是因爲您已經在使用此作爲條件。根據提供的數據集,有相同的ID,這就是我發佈這兩種解決方案的原因。爲了縮放您已經編寫的方法,無法縮放更大的數據,這就是爲什麼我將它稱爲*快速入侵* –

+0

示例數據集是一個刪節,可能不完全反映實際數據。那麼如何通過'device_id'獲取進入和退出設備? 'coalesce'可用於獲取第一個非空'device_id'而不是'substring'和'group_concat'。 此外,有什麼建議如何更好地查詢這些問題? – Shuvo

0

爲了避免加入我建議你試試 「相關子查詢」,而不是:

select 
    employee_id 
    , logdate 
    , TIME(entry_time)      entry_time 
    , (select MIN(l.device_id) 
    from attendance_logs l 
    where l.employee_id = d.employee_id 
    and l.logged_time = d.entry_time)  entry_device 
    , TIME(exit_time)      exit_time 
    , (select MAX(l.device_id) 
    from attendance_logs l 
    where l.employee_id = d.employee_id 
    and l.logged_time = d.exit_time)  exit_device 
from (
     select 
      attendance_logs.employee_id 
     , DATE(attendance_logs.logged_time) as logdate 
     , MIN(attendance_logs.logged_time) as entry_time 
     , MAX(attendance_logs.logged_time) as exit_time 
     from attendance_logs 
     group by 
      attendance_logs.employee_id 
     , DATE(attendance_logs.logged_time) 
    ) d 
; 

見:http://sqlfiddle.com/#!9/06e0e2/3

注:我已經對這些子查詢使用MIN()和MAX()只是爲了避免這些返回多個值的可能性。如果您願意,您可以使用限制1

另請注意:我通常不推薦關聯的子查詢,因爲它們可能會導致性能問題,但它們確實會提供所需的數據。

哦,請儘量避免使用date作爲列名,這不是好習慣。

+0

如果外部查詢結果集非常大,那麼不相關的子查詢會成爲性能問題嗎? 由於結果集很大,我避免了相關的子查詢。實際的表格可能會有2百萬或更多的記錄並在不斷增長。查詢分頁,但一次獲取500。 – Shuvo

+0

Yee(正如我已經說過的)。你排除了連接,所以可用選項減少。就我看到它而言,你被這些相關的查詢所困住。 –

相關問題