2017-03-19 5 views
0

私のテーブルにはクロックアウト時間が保存されていますが、そのうちのいくつかは1回以上パンチします。どのように最新結果を得るには?結果が複数ある場合はどこかで

SELECT 
    ROW_NUMBER() OVER (PARTITION BY l.USERID, day(l.CHECKTIME), DATEPART(hh, l.CHECKTIME) ORDER BY (select 0)) RN, 
    l.USERID, 
    CASE 
     WHEN CAST(l.CHECKTIME AS TIME) > = CAST(SC.EndTime AS TIME) 
      THEN CONVERT(VARCHAR(10), CAST(l.CHECKTIME AS TIME), 100) 
      ELSE 'Early ClockOut ' + CONVERT(VARCHAR(100), CAST(l.CHECKTIME AS TIME), 100) 
    END as ClockOut,l.CHECKTIME 
FROM 
    CHECKINOUT l 
INNER JOIN 
    USERINFO u ON l.USERID = u.USERID 
INNER JOIN 
    UserUsedSClasses uuc ON uuc.USERID = u.USERID 
INNER JOIN 
    SchClass SC ON uuc.SchId = SC.schClassid 
WHERE 
    u.BADGENUMBER not in (79,103,78) 
    AND MONTH(CHECKTIME) = MONTH(getdate()) AND YEAR(CHECKTIME) = YEAR(getdate()) 
    AND uuc.SchId = 1 
    AND DATEPART (hh, l.CHECKTIME) >= DATEPART(hh, SC.EndTime) 
    AND DATEPART(hh, l.CHECKTIME) >= DATEPART (hh, SC.StartTime) 
ORDER BY 
    u.BADGENUMBER 

出力:

RN USERID ClockOut CHECKTIME 
1 6  7:04PM  2017-03-09 19:04:12.000 
2 6  7:55PM  2017-03-09 19:55:59.000 
1 6  11:31PM  2017-03-09 23:31:27.000 

にのみ、この結果を表示する必要があります:あなたのrow_number()

RN USERID ClockOut CHECKTIME 
----------------------------------------------- 
1 6  11:31PM  2017-03-09 23:31:27.000 

答えて

2

、あなたのorder byl.CHECKTIME descに変更してからcommon table expressionまたは副問合せを使用してwhere rn = 1にフィルタリングします。

partition byl.userid, dateadd(day, datediff(day, 0, l.checktime), 0)に変更して、日時のみを日付に切り捨てます(convert(date,l.checktime)も使用できます)。

common table expressionを使用して:

;with cte as (
    select 
     rn = row_number() over (
     partition by l.userid, dateadd(day, datediff(day, 0, l.checktime), 0) 
     order by l.checktime desc 
    ) 
    , l.userid 
    , Clockout = case 
     when cast(l.checktime as time) >= cast(sc.EndTime as time) 
      then convert(varchar(100), cast(l.checktime as time), 100) 
     else 'Early ClockOut ' + convert(varchar(100), cast(l.checktime as time), 100) 
     end 
    , l.checktime 
    , u.badgenumber 
    from checkinout l 
    inner join userinfo u 
     on l.userid = u.userid 
    inner join UserUsedsclasses uuc 
     on uuc.userid = u.userid 
    inner join SchClass sc 
     on uuc.SchId = sc.schClassid 
    where uuc.SchId = 1 
    and u.badgenumber not in (79, 103, 78) 
    and l.checktime >= dateadd(month, datediff(month, 0, getdate()) , 0) 
    and l.checktime < dateadd(month, datediff(month, 0, getdate())+1, 0) 
    and datepart(hour, l.checktime) >= datepart(hour, sc.EndTime) 
    and datepart(hour, l.checktime) >= datepart(hour, sc.StartTime) 
) 
select * 
from cte 
where rn = 1 
order by badgenumber; 

またはCTE

select * 
from (
    select 
     rn = row_number() over (
     partition by l.userid, dateadd(day, datediff(day, 0, l.checktime), 0) 
     order by l.checktime desc 
    ) 
    , l.userid 
    , Clockout = case 
     when cast(l.checktime as time) >= cast(sc.EndTime as time) 
      then convert(varchar(100), cast(l.checktime as time), 100) 
     else 'Early ClockOut ' + convert(varchar(100), cast(l.checktime as time), 100) 
     end 
    , l.checktime 
    , u.badgenumber 
    from checkinout l 
    inner join userinfo u 
     on l.userid = u.userid 
    inner join UserUsedsclasses uuc 
     on uuc.userid = u.userid 
    inner join SchClass sc 
     on uuc.SchId = sc.schClassid 
    where uuc.SchId = 1 
    and u.badgenumber not in (79, 103, 78) 
    and l.checktime >= dateadd(month, datediff(month, 0, getdate()) , 0) 
    and l.checktime < dateadd(month, datediff(month, 0, getdate())+1, 0) 
    and datepart(hour, l.checktime) >= datepart(hour, sc.EndTime) 
    and datepart(hour, l.checktime) >= datepart(hour, sc.StartTime) 
) as sub 
where rn = 1 
order by badgenumber; 

そして実行するためのより高速な方法はない:

AND MONTH(CHECKTIME) = MONTH(getdate()) 
AND YEAR(CHECKTIME) = YEAR(getdate()) 

です
and l.checktime >= dateadd(month, datediff(month, 0, getdate()) , 0) /* month start*/ 
and l.checktime < dateadd(month, datediff(month, 0, getdate())+1, 0) /* next month start */ 
関連する問題