使用光标返回函数

时间:2014-02-17 09:03:03

标签: sql sql-server cursor ssms

我当前的表格是:

USERID  Department    NAME           actualdate
 522    xyz department  John Wayne    2/17/14 8:34
 522    xyz department  John Wayne    2/17/1411:21
 789    xyz department  Bill Smith    2/17/14 9:41
 789    xyz department  Bill Smith    2/17/14 11:16
 789    xyz department  Bill Smith    2/17/14 11:50
 789    xyz department  Bill Smith    2/17/14 12:18
 856    xyz department  Raul Castil   2/17/14 9:25

我想创建一个允许我输入用户ID并从该用户返回数据的函数。但是,我想取第一行并获取实际日期,然后将其存储在列'check in'中,并将最后一行存储在列调用中'检出'。

基本上每天我都要记录用户的入住时间并查看每天的时间。

这就是我到目前为止所做的“

CREATE FUNCTION [dbo].[GetEmployeeTime]
(   
@useridd int
)
RETURNS @RtnValue TABLE 
(
    useridd int,
    deptname varchar(max),
    emplname varchar(100),
    actualDate datetime,
    checkIn datetime,--first row of the actual date goes here
    checkOut datetime -- last row of the actual date goes here
)
AS
BEGIN
DECLARE  @userid int,@checkin datetime, @checkout datetime;
    DECLARE @useridAndDate   varchar(max), @useridAndDate2 varchar(max);

    DECLARE Curs CURSOR FOR 
    select ch.USERID AS useridd,ch.CHECKTIME as actualdate
    from CHECKINOUT ch
    left join USERINFO ui on ui.USERID=ch.USERID
    left join DEPARTMENTS dep on dep.DEPTID=ui.DEFAULTDEPTID

 OPEN Curs;
 FETCH NEXT FROM Curs INTO  @useridd, @actualdate;
 WHILE @@FETCH_STATUS=0

 ---so confuse here to loop through rows to record only first and last row.
   set @useridAndDate= @useridd + @actualdate
   --if @useridAndDate != @useridAndDate2
   --begin
   --end

FETCH NEXT FROM Curs INTO @useridd,@actualdate
close Curs;
deallocate Curs;
Return;

END

我希望最终结果如下:

USERID    Department       NAME    actualdate       checkin       checkout    
 522     xyz department   John Wayne    2/17/14 8:34   2/17/14 8:34   2/17/14 11:21
 789     xyz department   Bill Smith    2/17/14 9:41   2/17/14 9:41   2/17/14 12:18
 856     xyz department   Raul Castil   2/17/14 9:25   2/17/14 9:25

2 个答案:

答案 0 :(得分:1)

  

这不需要Cursor。你只需要分区   每个用户的最大值和最小值,只需区分它们

SELECT DISTINCT USERID,Department,NAME,FIR checkTime,
CASE WHEN FIR=SEC THEN NULL ELSE SEC END checkOut 
FROM
(
    SELECT *,
    MIN(CAST(CHECKTIME AS TIME)) OVER (PARTITION BY(USERID))FIR, 
    MAX(CAST(CHECKTIME AS TIME)) OVER (PARTITION BY(USERID))SEC 
    FROM TimePunch
)TAB

答案 1 :(得分:0)

你可以用GROUP BY做到这一点。

游标有很大的开销,虽然对程序控制很有用,但它们通常不适合回答基于集合的查询。

具有DATEADD(DAY, 0, DATEDIFF(DAY, 0, actualdate))的部分只会将该值截断到当天的开头,因此我可以在不同日期获取签到和结帐。我假设它是某种类型的DATETIME数据类型,并且舍入它使用的方法几乎适用于所有版本的SQL Server(因为你没有指定你正在使用的那个)。

SELECT
  USERID,
  Department,
  NAME,
  DATEADD(DAY, 0, DATEDIFF(DAY, 0, actualdate))   AS date,
  MIN(CHECKTIME)                                  AS checkIn,
  MAX(CHECKTIME)                                  AS checkOut
FROM
  CHECKINOUT
GROUP BY
  1, 2, 3, 4

注意:如果任何日期字段是字符串,则可能存在问题。然后,我强烈建议改变事物,使它们成为DATETIME / TIME / DATE字段。