補全未出勤日期

-- 建立测试环境
set  nocount  on
create   table  test(Name  varchar ( 20 ),Date  varchar ( 20 ),Time1  varchar ( 20 ),Time2  varchar ( 20 ))
insert   into  test  select   ' xxxx ' , ' 2008-2-1 ' , ' 08:00 ' , ' 17:00 '
insert   into  test  select   ' xxxx ' , ' 2008-2-9 ' , ' 08:00 ' , Null
insert   into  test  select   ' xxxx ' , ' 2008-2-28 ' , ' 08:00 ' , ' 17:00 '
go
-- 测试

select    case   when   isdate (date) > 0   then  name  else   ' - '   end  EmpName,
        
case   when   isdate (date) > 0   then  date  else   ' - '   end  IODate,
        Time1,Time2
    
from (
select  ( select   max (name)  from  test)name,
(
select   cast ( year ( max ( cast (date  as   datetime )))  as   varchar ( 4 )) + ' - ' +
        
cast ( month ( max ( cast (date  as   datetime )))  as   varchar ( 2 )) + ' - ' +
        
cast (b.dd  as   varchar ( 2 ))  from  test)date,
        
isnull (time1, ' - ' ) time1, isnull (time2, ' - ' ) time2
 
 
from  test a
right   join ( select   1   as  dd  union   select   2   union   select   3   union   select   4   union   select   5   union
    
select   6   union   select   7   union   select   8   union   select   9   union   select   10   union
    
select   11   union   select   12   union   select   13   union   select   14   union   select   15   union
    
select   16   union   select   17   union   select   18   union   select   19   union   select   20   union
    
select   21   union   select   22   union   select   23   union   select   24   union   select   25   union
    
select   26   union   select   27   union   select   28   union   select   29   union   select   30   union
    
select   31 ) b
on   day ( cast (date  as   datetime )) = b.dd)a


-- 删除测试环境
drop   table  test
 
set  nocount  off
/*
EmpName              IODate     Time1                Time2                
-------------------- ---------- -------------------- -------------------- 
xxxx                 2008-2-1   08:00                17:00
xxxx                 2008-2-2   -                    -
xxxx                 2008-2-3   -                    -
xxxx                 2008-2-4   -                    -
xxxx                 2008-2-5   -                    -
xxxx                 2008-2-6   -                    -
xxxx                 2008-2-7   -                    -
xxxx                 2008-2-8   -                    -
xxxx                 2008-2-9   08:00                -
xxxx                 2008-2-10  -                    -
xxxx                 2008-2-11  -                    -
xxxx                 2008-2-12  -                    -
xxxx                 2008-2-13  -                    -
xxxx                 2008-2-14  -                    -
xxxx                 2008-2-15  -                    -
xxxx                 2008-2-16  -                    -
xxxx                 2008-2-17  -                    -
xxxx                 2008-2-18  -                    -
xxxx                 2008-2-19  -                    -
xxxx                 2008-2-20  -                    -
xxxx                 2008-2-21  -                    -
xxxx                 2008-2-22  -                    -
xxxx                 2008-2-23  -                    -
xxxx                 2008-2-24  -                    -
xxxx                 2008-2-25  -                    -
xxxx                 2008-2-26  -                    -
xxxx                 2008-2-27  -                    -
xxxx                 2008-2-28  08:00                17:00
xxxx                 2008-2-29  -                    -
-                    -          -                    -
-                    -          -                    -
*/


水晶報表做法參考: http://www.cnblogs.com/babyt/archive/2008/05/11/1192770.html
为了计算每位员工截至每个出勤日期为止的连续出勤天数,可以利用窗口函数和一些巧妙的时间差逻辑。以下是具体的SQL查询思路及实现步骤: ### SQL 查询 假设您的表名叫做 `attendance_table` ,结构为: - `employee_id`: 员工ID - `attendance_date`: 出勤日期 - `attendance_time`: 出勤时间(>0 表示已出勤,=0 或 NULL 表示出勤) #### 实现方案 我们先通过窗口函数对数据进行编号,再判断哪些日子是真正意义上的"断档"(即某天没打卡),以此为基础来计算连续工作日的数量。 ```sql WITH ContinuousAttendance AS ( SELECT employee_id, attendance_date, attendance_time, CASE WHEN LAG(attendance_time, 1) OVER w <= 0 OR attendance_time > 0 THEN ROW_NUMBER() OVER w ELSE 0 END - ROW_NUMBER() OVER (PARTITION BY employee_id ORDER BY attendance_date) + 1 AS grp FROM attendance_table WINDOW w AS (PARTITION BY employee_id ORDER BY attendance_date) ), GroupedContinuousDays AS ( SELECT *, SUM(grp) OVER (PARTITION BY employee_id ORDER BY attendance_date) AS group_num FROM ContinuousAttendance ) SELECT gcd.employee_id, gcd.attendance_date, COUNT(*) OVER (PARTITION BY gcd.employee_id, gcd.group_num ORDER BY gcd.attendance_date) AS consecutive_days FROM GroupedContinuousDays gcd WHERE gcd.attendance_time > 0; -- 只统计有效的工作日 ORDER BY gcd.employee_id, gcd.attendance_date; ``` **说明** 1. **第一步**: 使用窗口函数 `LAG()` 来查看前一天是否有记录,并结合 `ROW_NUMBER()` 计算当天是否应该属于新的连贯序列。 2. **第二步**: 对每一个新开始的连贯段赋予一个新的标识符 (`group_num`)。 3. **第三步**: 根据这个标识符再次分组并计数每一段内有多少个工作日。 最终输出包括三个字段: - `employee_id`: 每位雇员的身份识别码; - `attendance_date`: 当前检查的日志日期; - `consecutive_days`: 截止到这一天该员工已经持续工作的总天数(仅当 `attendance_time` 大于零时才计入)。 这种方法能有效地追踪每个人每天的实际状态变化情况,并且准确地反映出他们各自最新的连续上班周期长度。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值