Loops 使用游标更新临时表中的记录

Loops 使用游标更新临时表中的记录,loops,cursor,sql-server-2012,Loops,Cursor,Sql Server 2012,我试图创建一个游标,在临时表中插入第一条记录。 之后,它应获取下一条记录,并将employeeId+日期格式2014年5月5日与上一条记录employeeId+日期进行比较。若相同,则应使用当前记录超时数据更新以前的记录超时数据。 否则它应该插入新行 I have table in my database with the following columns: employeeID(int), employeeName varchar(max), Time datetime. 1

我试图创建一个游标,在临时表中插入第一条记录。 之后,它应获取下一条记录,并将employeeId+日期格式2014年5月5日与上一条记录employeeId+日期进行比较。若相同,则应使用当前记录超时数据更新以前的记录超时数据。 否则它应该插入新行

I have table in my database with the following columns:
 employeeID(int), employeeName varchar(max), Time datetime.
     1          ,   Tim                    , 05/05/2014 08:15:42
     1          ,   Tim                    , 05/05/2014 16:30:51
     1          ,   Tim                    , 06/23/2014 07:00:00
     1          ,   Tim                    , 06/23/2014 09:00:00
     1          ,   Tim                    , 06/23/2014 11:00:00
     1          ,   Tim                    , 06/23/2014 16:30:00
我创建了一个包含以下列的临时表,最终结果应该如下面的信息所示

employeeID, employeeName ,  Time in            ,    Time out
 1          ,   Tim   , 05/05/2014 08:15:42 ,    05/05/2014 16:30:51
 1          ,   Tim   , 06/23/2014 07:00:00      06/23/2014 16:30:00
下面是我的代码

    Drop Table #temp
 go
 Create Table #temp 
 (
userid int,
empname varchar(50),
checkin datetime,
checkout datetime
 )


 Declare @empid int, @empname varchar(50), @date1 datetime, @strdate varchar(12);
 Declare @date2 datetime, @time datetime, @loop int;


 Declare Report Cursor
For select e.employeeId,e.name,tp.TimePunch, tp.TimePunch as date2,
    CONVERT(VARCHAR(10),TimePunch,110) as stringDate
    from EmpTimePunch tp
    left join EmploeeInfo e on tp.employeeId = tp.employeeId
    where (DATEDIFF(s,'2014-05-01 00:00:00.000',TimePunch) >=0 
    and DATEDIFF(s,getdate(),TimePunch)<=0)
    order by employeeId,TimePunch

Open Report 
-- looking at each record 
Fetch Next From Report
    Into @empid, @empname, @date1, @date2,@strdate

declare @empDate varchar(50);
declare @empDate2 varchar(50);
set @empDate = '';
set @empDate2 = '';
set @loop = 0
--0 equals true; while fetching equal true 
while @@FETCH_STATUS = 0

    Begin
    -- insert first record in temp table
        if @loop != 0 and @empDate = @empDate2
            insert into #temp values(@empid, @empname, @date1, @date2)

            --I want to compare the next record
            -- if next record have same employee id and date2(05/05/2014) as prievous record.
            --update previous record date2 with the date2 from record 2
            set @empDate = cast(@empid as varchar(10))+ @strdate;

        fetch next from report
            Into @empid, @empname, @date1, @date2,@strdate

    End
close Report
Deallocate Report

select * from #temp

根据经验,在SQL中应该避免迭代逻辑。 只要有可能,就应该利用语言的声明性本质——将代码表示为基于集合的查询

我提出这样或类似的解决方案

;WITH MyData (employeeID, employeeName, [Time])  
AS
(
    SELECT 1, 'Tim', '05/05/2014 08:15:42' UNION ALL
    SELECT 1, 'Tim', '05/05/2014 16:30:51' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 07:00:00' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 09:00:00' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 11:00:00' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 16:30:00'
)
SELECT   employeeID
        ,employeeName
        ,[Time In]  = MIN([Time])
        ,[Time Out] = MAX([Time])
FROM MyData
GROUP BY employeeID, employeeName, CAST([Time] AS DATE)
如果您对CTEs不熟悉或不舒服

脚注;
我相信,当我提出游标是您在SQL中最不应该尝试学习的东西时,我的观点会得到回应。这将有希望迫使你尝试基于集合的方法。

你会接受非基于游标的解决方案吗?我正在尝试学习游标,所以我强迫自己使用它们。不过,我想看看如何用另一种方式来做,并对它进行评估,看看它是否能满足我的需求。非常欢迎。如果您手头有时间,请尝试找出光标并运行一些性能测试以监控差异:
CREATE TABLE #MyData
(
    employeeID      INT, 
    employeeName    VARCHAR(50),    --  Please use VARCHAR(MAX) as infrequently as possible 
    ClockTime       DATETIME        --  In this example, I've changed the field name from [Time] to ClockTime           
)                                   --  It is best to avoide reserved words for object\field naming

INSERT INTO #MyData (employeeID, employeeName, ClockTime)
    SELECT 1, 'Tim', '05/05/2014 08:15:42' UNION ALL
    SELECT 1, 'Tim', '05/05/2014 16:30:51' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 07:00:00' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 09:00:00' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 11:00:00' UNION ALL
    SELECT 1, 'Tim', '06/23/2014 16:30:00'

SELECT   employeeID
        ,employeeName
        ,[Time In]  = MIN(ClockTime)
        ,[Time Out] = MAX(ClockTime)
FROM #MyData
GROUP BY employeeID, employeeName, CAST(ClockTime AS DATE)