2017-06-29 4 views
1

毎日各従業員のクロックインとクロックアウトを調べる必要があります。それは2シフトを持ち、最初のシフトは0830 - 2030から始まり、2番目のシフトは2030 - 0830(翌日)からです。以下は、私が持っているサンプルレコード、 異なるシフトのタイムインとタイムアウトの選択

Time In     Time Out    User 
2017-06-16 07:30:00.000 2017-06-16 08:30:00.000 I0495 
2017-06-16 08:30:00.000 2017-06-16 12:30:00.000 I0495 
2017-06-16 13:00:00.000 2017-06-16 15:30:00.000 I0495 
2017-06-16 15:30:00.000 2017-06-16 19:00:00.000 I0495 

2017-06-16 20:30:00.000 2017-06-16 21:30:00.000 I0603 
2017-06-16 21:30:00.000 2017-06-17 00:00:00.000 I0603 
2017-06-17 00:00:00.000 2017-06-17 00:30:00.000 I0603 
2017-06-17 01:30:00.000 2017-06-17 04:30:00.000 I0603 
2017-06-17 05:30:00.000 2017-06-17 08:30:00.000 I0603 

2017-06-17 07:30:00.000 2017-06-17 08:30:00.000 I0495 
2017-06-17 08:30:00.000 2017-06-17 12:30:00.000 I0495 
2017-06-17 13:00:00.000 2017-06-17 15:30:00.000 I0495 
2017-06-17 15:30:00.000 2017-06-17 19:00:00.000 I0495 

は、私は私が得る結果

Select min(tbl.timein), max(tbl.timeout), tbl.user form 
(
Select timein, timeout, user from tbl where timein >= '2017-06-16 
07:00:00' and timeout <= '2017-06-16 20:30:00' 
union all 
Select timein, timeout, user from tbl where timein >= '2017-06-16 
20:60:00' and timeout <= '2017-06-17 08:30:00' 
)tbl 
group by tb.user 

以下のようにクエリを試すには、これを下回ると予想されていないと何されている

2017-06-16 07:30:00.000 2017-06-17 08:30:00.000 I0495 
2017-06-16 20:30:00.000 2017-06-17 08:30:00.000 I0603 
2017-06-17 07:30:00.000 2017-06-18 08:30:00.000 I0495 

期待される結果are

どのように私はこれを行うことができます任意のアイデア。ありがとう。

+1

SQL Serverのバージョンを使用していますか? –

+0

最初のシフトが「8:30 am」から始まる場合、期待される結果セットで「7:30 am」から範囲を報告するのはなぜですか? –

+0

@TimBiegeleisen一部の従業員が早期に入居を要求するため、午前7時に入居することがあります。これは私が期待した結果を得ることができない問題です –

答えて

0

これを解決するための合理的な方法は、ユーザーがタイムアウトと次のタイムインの間に取ることができる最大のブレークを知ることです。 < = 2時間と仮定すると、前回のタイムアウトと現在の行のタイムインとの差をユーザーごとに取得することでこれを行うことができます。次に、実行中の合計を使用して、これに基づいて1日あたりのグループを割り当てます。

select usr,timein,timeout 
,sum(case when diff <=120 then 0 else 1 end) over(partition by usr order by timein) as grp 
from (select t.* 
     ,datediff(minute,lag(timeout) over(partition by usr order by timein),timein) as diff 
     from tbl t 
    ) t 

グループが割り当てられた後、あなただけmin timeinユーザーおよびグループごとmaxタイムアウトを必要とします。

select usr,min(timein),max(timeout) 
from (select usr,timein,timeout 
     ,sum(case when diff <=120 then 0 else 1 end) over(partition by usr order by timein) as grp 
     from (select t.* 
      ,datediff(minute,lag(timeout) over(partition by usr order by timein),timein) as diff 
      from tbl t 
      ) t 
    ) t 
group by usr,grp 
+0

この問題はItzik Ben-Ganが記事「Packing Intervals」(http://blogs.solidq.com/en/sqlserver/packing-intervals/)で説明したように、記事の最後のセクション「Ignoring Gap of Up toある長さ "。 –

0

多分、これはあなたにも役立ちます。

出典:

  DECLARE @T TABLE 
       (
        TimeIn DATETIME , 
        [TimeOut] DATETIME , 
        [User] VARCHAR(50) 
       ) 

      INSERT INTO @T 
        (TimeIn, TimeOut, [User]) 
      VALUES ('2017-06-16 07:30:00.000', '2017-06-16 08:30:00.000', 'I0495'), 
        ('2017-06-16 08:30:00.000', '2017-06-16 12:30:00.000', 'I0495'), 
        ('2017-06-16 13:00:00.000', '2017-06-16 15:30:00.000', 'I0495'), 
        ('2017-06-16 15:30:00.000', '2017-06-16 19:00:00.000', 'I0495'), 
        ('2017-06-16 20:30:00.000', '2017-06-16 21:30:00.000', 'I0603'), 
        ('2017-06-16 21:30:00.000', '2017-06-17 00:00:00.000', 'I0603'), 
        ('2017-06-17 00:00:00.000', '2017-06-17 00:30:00.000', 'I0603'), 
        ('2017-06-17 01:30:00.000', '2017-06-17 04:30:00.000', 'I0603'), 
        ('2017-06-17 05:30:00.000', '2017-06-17 08:30:00.000', 'I0603'), 
        ('2017-06-17 07:30:00.000', '2017-06-17 08:30:00.000', 'I0495'), 
        ('2017-06-17 08:30:00.000', '2017-06-17 12:30:00.000', 'I0495'), 
        ('2017-06-17 13:00:00.000', '2017-06-17 15:30:00.000', 'I0495'), 
        ('2017-06-17 15:30:00.000', '2017-06-17 19:00:00.000', 'I0495'); 

問合せ:

  IF (OBJECT_ID('tempdb..#tmpTbl') IS NOT NULL) 
       BEGIN 
        DROP TABLE #tmpTbl 
       END 
      CREATE TABLE #tmpTbl 
       (
        id INT IDENTITY(1, 1) 
         PRIMARY KEY , 
        TimeIn DATETIME , 
        [TimeOut] DATETIME , 
        [User] VARCHAR(50) , 
        flag INT , 
        [lag] INT 
       ) 

      INSERT INTO #tmpTbl 
        (TimeIn , 
         TimeOut , 
         [User] , 
         flag , 
         lag 
        ) 
        SELECT TimeIn , 
          TimeOut , 
          [User] , 
          flag , 
          LAG(flag) OVER (ORDER BY ctr) LAG 
        FROM (SELECT * , 
             IIF(CAST(TimeIn AS TIME) BETWEEN '7:00' AND '8:30', 1, IIF(CAST(TimeIn AS TIME) >= '20:30', 1, 0)) flag , 
             ROW_NUMBER() OVER (ORDER BY (SELECT 
                      0 
                    )) ctr 
           FROM  @T 
          ) TT 

      DECLARE @Lastid INT 
      SELECT TOP 1 
        @Lastid = id 
      FROM #tmpTbl 
      ORDER BY id DESC 

      UPDATE #tmpTbl 
      SET  flag = 2 
      WHERE id = @Lastid 

      UPDATE #tmpTbl 
      SET  flag = 0 
      WHERE lag = 1 

      UPDATE #tmpTbl 
      SET  flag = 2 
      WHERE id IN (SELECT previd 
          FROM (SELECT flag , 
               LAG(flag) OVER (ORDER BY ID) lag , 
               LAG(id) OVER (ORDER BY ID) previd 
             FROM  #tmpTbl 
            ) T 
          WHERE T.flag = 1 
            AND T.lag = 0); 
      WITH CTE 
         AS (SELECT * , 
            ROW_NUMBER() OVER (ORDER BY id) ctr 
          FROM  #tmpTbl 
          WHERE flag = 1 
         ), 
        CTE1 
         AS (SELECT * , 
            ROW_NUMBER() OVER (ORDER BY id) ctr 
          FROM  #tmpTbl 
          WHERE flag = 2 
         ), 
        CTE2 
         AS (SELECT cte.TimeIn , 
            cte1.TimeOut , 
            cte.[user] 
          FROM  cte 
            JOIN cte1 ON CTE1.ctr = CTE.ctr 
         ) 
       SELECT * 
       FROM CTE2 

結果:

 TimeIn     TimeOut     user 
     ----------------------- ----------------------- ------- 
     2017-06-16 07:30:00.000 2017-06-16 19:00:00.000 I0495 
     2017-06-16 20:30:00.000 2017-06-17 08:30:00.000 I0603 
     2017-06-17 07:30:00.000 2017-06-17 19:00:00.000 I0495 

     (3 row(s) affected) 
関連する問題