0

我有一张表,它根据用户名存储员工通过 Time Machine 的签到时间。如果一个员工多次打卡,那么他的签到记录会有多条记录,它们之间只有几秒钟的时间差。显然只有第一条记录是有效的。所有其他条目均无效,必须从表中删除。如果我可以选择员工当前日期的所有签到记录,我该怎么做?

db中的数据如下。

Username               Checktime                       CheckType
 HRA001            7/29/2012 8:16:44 AM                Check-In
 HRA001            7/29/2012 8:16:46 AM                Check-In
 HRA001            7/29/2012 8:16:50 AM                Check-In 
 HRA001            7/29/2012 8:16:53 AM                Check-In 
4

8 回答 8

1

尝试这个:

 ;WITH users_CTE as (
 select rank() over (partition by Username order by Checktime) as rnk from users
 )

 DELETE FROM users_CTE where rnk <> 1

--对于您的第二个要求,请尝试此查询

 ;WITH users_CTE as (
 select *,rank() over (partition by Username order by Checktime) as rnk from users
 )
,CTE2 as (select Username,MIN(CheckTime) as minTime,DATEADD(mi,1,MIN(CheckTime)) as maxTime from users_CTE 
 group by Username)



delete from users where Checktime in(
select c1.Checktime from users_CTE c1 left join CTE2 c2
on c1.Checktime > c2.minTime and c1.Checktime <= c2.maxTime
where c2.Username is not null and c1.Username in(

select c1.Username from users_CTE c1 left join CTE2 c2
on c1.Checktime > c2.minTime and c1.Checktime <= c2.maxTime
group by c1.Username,c2.Username 
having COUNT(*) > 1))

--对于您更改的要求,请在下面检查此查询

alter table users add flag varchar(2)

;WITH users_CTE as (
 select *,rank() over (partition by Username order by Checktime) as rnk from users
 )
,CTE2 as (select Username,MIN(CheckTime) as minTime,DATEADD(mi,1,MIN(CheckTime)) as maxTime from users_CTE 
 group by Username)


update u SET u.flag = 'd' from users_CTE u inner join (
select c1.Checktime from users_CTE c1 left join CTE2 c2
on c1.Checktime > c2.minTime and c1.Checktime <= c2.maxTime
where c2.Username is not null and c1.Username in(

select c1.Username from users_CTE c1 left join CTE2 c2
on c1.Checktime > c2.minTime and c1.Checktime <= c2.maxTime
group by c1.Username,c2.Username 
having COUNT(*) > 1)) a
on u.Checktime=a.Checktime

--用DeletFlag检查最新查询

;WITH users_CTE as 
(
 select *,row_number() over (partition by Username order by Checktime) as row from users
)
,CTE as(
select row,Username,Checktime,CheckType,0 as totalSeconds,'N' as Delflag from users_CTE where row=1 
union all
select t.row,t.Username,t.Checktime,t.CheckType,CASE WHEN (c.totalSeconds + DATEDIFF(SECOND,c.Checktime,t.Checktime))  >= 60 then 0 else (c.totalSeconds + DATEDIFF(SECOND,c.Checktime,t.Checktime)) end as totalSeconds,
CASE WHEN (c.totalSeconds + DATEDIFF(SECOND,c.Checktime,t.Checktime))  >= 60 then 'N' else 'Y' end as Delflag
--CASE WHEN c.totalSeconds <= 60  then 'Y' else 'N' end as Delflag
from users_CTE t inner join CTE c
on t.row=c.row+1
)

select Username,Checktime,CheckType,Delflag from CTE
于 2012-08-07T06:53:15.627 回答
0

http://codesimplified.com/2010/10/18/remove-duplicate-records-from-the-database-table/

希望这会帮助你。

于 2012-08-07T06:01:32.000 回答
0
DELETE FROM timesheet 
WHERE timesheetRecordId <>(
                SELECT TOP 1 timesheetRecordId from timesheet  
                WHERE checkInDate=todaysDate AND employeeId=empId ORDER BY checkInTime ASC
               ) 
AND checkInDate=today's date AND empolyeeId=empId;
于 2012-08-07T06:15:43.970 回答
0

您可以尝试按签到时间对记录进行排名,然后删除每个员工每天所有排名大于 1 的记录。

于 2012-08-07T05:52:51.497 回答
0

为什么不在将签入插入到数据库之前验证签入。如果该用户存在任何签到,则在此日期和该日期之间,然后不执行任何其他操作插入它

于 2012-08-07T05:45:47.977 回答
0

您应该能够按时间对所有记录进行排序,从每个员工上一次的时间中减去最近的时间,如果结果小于某个阈值,则删除具有最近时间的行。

于 2012-08-07T05:48:30.007 回答
0

试试这个查询: Delete from employee where employee.checkin (select checkin from employee where count(checkin)>1);

于 2012-08-07T05:57:49.157 回答
0

我认为您不能在同一语句的子查询中从 Delete 语句中指定目标表。所以你不能用一个单独的 Delete 语句来做到这一点。

您可以做的是编写一个存储过程。在您的存储过程中,您应该创建一个包含此查询返回的 PK 的临时表:

select cht.pkey 
  from CheckTimeTable as cht
  where exists ( select pkey
                   from CheckTimeTable 
                   where username = cht.userName
                     and checkType = 'check-IN'
                     and Checktime >= subtime(cht.Checktime, '0 0:0:15.000000') 
                     and Checktime < cht.Checktime);

然后编写另一条语句从原始表 CheckTimeTable 中删除这些 PK。

请注意,上面的查询是针对 MySQL 的,因此您需要找到从 DBMS 的时间戳中减去 15 秒的方法。在 MySQL 中它是这样完成的:

subtime(cht.Checktime, '0 0:0:15.000000')

此查询将返回具有来自同一用户的另一个 CheckTime 记录的任何 CheckTime 记录,类型为 Check-In,并且在 15 秒内早于其自己的检查时间。

于 2012-08-07T08:29:30.930 回答