如何补齐考勤中的天数

Leshami
博客专家认证
2010-01-13 03:15:06
问题:
以下为考勤记录中的一部分,包含2009-07-01到2009-07-06日的考勤记录,
f_getdate函数为调用邹建所写的得到指定日期的工作日和休息日,附代码如下 。

if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_getdate]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_getdate]
GO

/*--生成列表

生成指定日期段的日期列表

--邹建 2005.03(引用请保留此信息)--*/

/*--调用示例

--查询工作日
SELECT * FROM dbo.f_getdate('2005-1-3','2005-4-5',0)

--查询休息日
SELECT * FROM dbo.f_getdate('2005-1-3','2005-4-5',1)

--查询全部日期
SELECT * FROM dbo.f_getdate('2005-1-3','2005-4-5',NULL)
--*/

CREATE FUNCTION dbo.f_getdate(
@begin_date Datetime, --要查询的开始日期
@end_date Datetime, --要查询的结束日期
@bz bit --@bz=0 查询工作日,@bz=1 查询休息日,@bz IS NULL 查询全部日期
)RETURNS @re TABLE(id int identity(1,1),Date datetime,Weekday nvarchar(3))
AS
BEGIN
DECLARE @tb TABLE(ID int IDENTITY(0,1),a bit)
INSERT INTO @tb(a) SELECT TOP 366 0
FROM sysobjects a ,sysobjects b

IF @bz=0
WHILE @begin_date<=@end_date
BEGIN
INSERT INTO @re(Date,Weekday)
SELECT Date,DATENAME(Weekday,Date)
FROM(
SELECT Date=DATEADD(Day,ID,@begin_date)
FROM @tb
)a WHERE Date<=@end_date
AND (DATEPART(Weekday,Date)+@@DATEFIRST-1)%7 BETWEEN 1 AND 5
SET @begin_date=DATEADD(Day,366,@begin_date)
END
ELSE IF @bz=1
WHILE @begin_date<=@end_date
BEGIN
INSERT INTO @re(Date,Weekday)
SELECT Date,DATENAME(Weekday,Date)
FROM(
SELECT Date=DATEADD(Day,ID,@begin_date)
FROM @tb
)a WHERE Date<=@end_date
AND (DATEPART(Weekday,Date)+@@DATEFIRST-1)%7 in(0,6)
SET @begin_date=DATEADD(Day,366,@begin_date)
END
ELSE
WHILE @begin_date<=@end_date
BEGIN
INSERT INTO @re(Date,Weekday)
SELECT Date,DATENAME(Weekday,Date)
FROM(
SELECT Date=DATEADD(Day,ID,@begin_date)
FROM @tb
)a WHERE Date<=@end_date
SET @begin_date=DATEADD(Day,366,@begin_date)
END

RETURN
END
GO
----------------------------------------------------------------------------------------
--要处理的代码,考勤中空值表示未打卡。

DECLARE @tab1 TABLE(CardNo INT ,Name NVARCHAR(25),Start_Work DATETIME ,End_Work DATETIME )
INSERT INTO @tab1
SELECT 1518665 , N'张三','2009-07-01 08:23:00.000' ,'2009-07-01 18:38:00.000'
UNION ALL SELECT 1518665 ,N'张三',NULL ,'2009-07-02 17:30:00.000'
UNION ALL SELECT 1518665 , N'张三','2009-07-03 08:08:00.000','2009-07-03 17:29:00.000'
UNION ALL SELECT 1518683 ,N'李四','2009-07-01 08:30:00.000' ,'2009-07-01 18:37:00.000'
UNION ALL SELECT 1518683 ,N'李四','2009-07-02 08:35:00.000' ,NULL
UNION ALL SELECT 1518683 ,N'李四','2009-07-04 10:09:00.000' ,'2009-07-04 18:06:00.000'
UNION ALL SELECT 1518683 ,N'李四',NULL , '2009-07-05 17:33:00.000'
UNION ALL SELECT 1518686 , N'王五', '2009-07-02 07:48:00.000', '2009-07-02 17:48:00.000'
UNION ALL SELECT 1518686 ,N'王五' , '2009-07-03 08:01:00.000','2009-07-03 18:11:00.000'
UNION ALL SELECT 1518686 ,N'王五' , '2009-07-06 07:51:00.000', '2009-07-06 18:40:00.000'

SELECT t.Name
,CONVERT(CHAR(10),s.Date,120) AS Date
,CONVERT(CHAR(8),RIGHT(t.Start_Work,8)) AS Start_Work
,CONVERT(CHAR(8),RIGHT(t.End_Work,8)) AS End_Work
,CASE s.Weekday WHEN 'Monday' THEN N'星期一'
WHEN 'Tuesday' THEN N'星期二'
WHEN 'Wednesday' THEN N'星期三'
WHEN 'Thursday' THEN N'星期四'
WHEN 'Friday' THEN N'星期五'
WHEN 'Saturday' THEN N'星期六'
WHEN 'Sunday' THEN N'星期天'
END AS Weekday
FROM dbo.f_getdate('2009-07-01','2009-07-06',null) AS s
LEFT JOIN @tab1 AS t
ON CONVERT(CHAR(10),s.Date,120) = CONVERT(CHAR(10),t.Start_Work,120)
OR CONVERT(CHAR(10),s.Date,120) = CONVERT(CHAR(10),t.End_Work,120)
ORDER BY s.Date ,t.CardNo

结果:
Name Date Start_Work End_Work Weekday
------------------------- ---------- ---------- -------- -------
张三 2009-07-01 8:23AM 6:38PM 星期三
李四 2009-07-01 8:30AM 6:37PM 星期三
张三 2009-07-02 NULL 5:30PM 星期四
李四 2009-07-02 8:35AM NULL 星期四
王五 2009-07-02 7:48AM 5:48PM 星期四
张三 2009-07-03 8:08AM 5:29PM 星期五
王五 2009-07-03 8:01AM 6:11PM 星期五
李四 2009-07-04 10:09AM 6:06PM 星期六
李四 2009-07-05 NULL 5:33PM 星期天
王五 2009-07-06 7:51AM 6:40PM 星期一

想要的结果:

Name Date Start_Work End_Work Weekday
------------------------- ---------- ---------- -------- -------
张三 2009-07-01 8:23AM 6:38PM 星期三
张三 2009-07-02 NULL 5:30PM 星期四
张三 2009-07-03 8:08AM 5:29PM 星期五
NULL 2009-07-04 NULL NULL 星期六
NULL 2009-07-05 NULL NULL 星期天
NULL 2009-07-06 NULL NULL 星期一
李四 2009-07-01 8:30AM 6:37PM 星期三
李四 2009-07-02 8:35AM NULL 星期四
NULL 2009-07-03 NULL NULL 星期五
李四 2009-07-04 10:09AM 6:06PM 星期六
李四 2009-07-05 NULL 5:33PM 星期天
NULL 2009-07-06 NULL NULL 星期一
NULL 2009-07-01 NULL NULL 星期三
王五 2009-07-02 7:48AM 5:48PM 星期四
王五 2009-07-03 8:01AM 6:11PM 星期五
NULL 2009-07-04 NULL NULL 星期六
NULL 2009-07-05 NULL NULL 星期天
王五 2009-07-06 7:51AM 6:40PM 星期一

问题:
1.如何对每个人分别得到1号到10号所有的记录,例如,张三7月1日至7月3日有记录,但4-10日没有记录,如何补齐?
2.因为我的环境为英文环境,如何将Start_Work或End_Work结果中的6:38PM换为18:36,如果是AM则省略掉即可。
3.结果中如果Name 能显示对应的名字更好
...全文
200 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiangjubo 2010-01-13
  • 打赏
  • 举报
回复
学习的!!!!!!!!!!!
Leshami 2010-01-13
  • 打赏
  • 举报
回复
left join 不行
比如张三 7月4日没有打卡,
但李四打卡了,故不能产生7月4日张三的记录。
--小F-- 2010-01-13
  • 打赏
  • 举报
回复
用1楼的语句和你的结果语句left join
SQL77 2010-01-13
  • 打赏
  • 举报
回复
SELECT 
DATEADD(DD,NUMBER,'2009-10-01')AS TIME
FROM
MASTER..SPT_VALUES
WHERE TYPE='P'
AND DATEADD(DD,NUMBER,'2009-10-01')<='2009-10-10'
TIME
------------------------------------------------------
2009-10-01 00:00:00.000
2009-10-02 00:00:00.000
2009-10-03 00:00:00.000
2009-10-04 00:00:00.000
2009-10-05 00:00:00.000
2009-10-06 00:00:00.000
2009-10-07 00:00:00.000
2009-10-08 00:00:00.000
2009-10-09 00:00:00.000
2009-10-10 00:00:00.000

(所影响的行数为 10 行)


产生缺失日期

27,580

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 应用实例
社区管理员
  • 应用实例社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧