ORACLE SQL 學習筆記4 統計員工最近連續加班次數和連續遲到次數

最近看到一個求助貼,說的是有一張考勤表,表結構爲: 員工編號 NO, 上班日期 DATE ,上班狀態 STATUS ( 0 正常上班 1 加班 2 遲到), 想統計所有員工最近連續加班次數,開始加班日期,結束加班日期,以及最近連續遲到次數,開始遲到日期,結束遲到日期。之前做過類似的統計,比如用戶連續訪問天數,打地鼠連續命中次數等,思路基本相同。這裏做一次詳細記錄:
一、準備數據
1.建表

create table stat_work
  (NO CHAR(4) NOT NULL,LOGIN_DATE DATE,STATUS NUMBER(1));

2.插入數據

INSERT INTO STAT_WORK values('1001',to_date('2020-01-17','yyyy-mm-dd'),2);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-16','yyyy-mm-dd'),2);
  INSERT INTO STAT_WORK values('1002',to_date('2020-01-16','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-15','yyyy-mm-dd'),2);
  INSERT INTO STAT_WORK values('1002',to_date('2020-01-15','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-14','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1002',to_date('2020-01-14','yyyy-mm-dd'),0);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-13','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1002',to_date('2020-01-13','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-12','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1002',to_date('2020-01-12','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1002',to_date('2020-01-11','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-10','yyyy-mm-dd'),1);
  INSERT INTO STAT_WORK values('1001',to_date('2020-01-09','yyyy-mm-dd'),0);
  commit;

數據如圖:
在這裏插入圖片描述
二、分步查詢數據
主要分以下幾步:
*1.*根據需求,對數據進行篩選。使用排名函數row_number() over()或rank() over()增加僞列,給每行數據添加序號,按no分區,按login_date排序。因爲數據行中login_date無重複數據,所以兩個函數都可以,甚至可以用dense_rank() over()。同時,增加列(login_date-序號),用以標記登陸日期-序號後的差值,命名爲diff_date。

select a.no,
               a.login_date,
               row_number() over(partition by a.no order by a.login_date) rn,
               a.login_date - row_number() over(partition by a.no order by a.login_date) diff_date
          from stat_work a
         where a.status = 1

執行結果如下圖:
在這裏插入圖片描述
從上圖可以看到,連續日期在減去其序號後的減值是相同的。所以,再根據diff_date進行分組並計數,個數在2以上的,即是連續天數,不管
*2.*在第1步的結果集基礎上,按no和diff_date進行分組統計。其原理是,登陸日期連續,則diff_date相同。

select b.no,
       min(b.login_date) 開始日期,
       max(b.login_date) 結束日期,
       count(*) 連續天數
  from (select a.no,
               a.login_date,
               row_number() over(partition by a.no order by a.login_date) rn,
               a.login_date - row_number() over(partition by a.no order by a.login_date) diff_date
          from stat_work a
         where a.status = 1) b
 group by b.no, b.diff_date
having count(*) >= 2
 order by 1, 2

查詢結果如下:在這裏插入圖片描述
說明:這種查詢關鍵是要理解思路和原理。其關鍵點就在於對diff_date的理解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章