2017-07-22 14 views
0

私は時間間隔のロジックに追いついていません。終了時刻と開始時刻の間に時間間隔がある場合は、そのデータを分離する必要があります。私はこのようなクエリを実行するために使用時間を処理する方法SQL Serverの間隔?

DECLARE @EMP_DETAILS TABLE 
        (ID INT, 
         EMP_ID INT, 
         START_TIME VARCHAR(10), 
         END_TIME VARCHAR(10) 
        ) 

INSERT INTO @EMP_DETAILS 
    SELECT 1, 50, '09:30', '10:30' 
    UNION 
    SELECT 2, 50, '10:30', '11:45' 
    UNION 
    SELECT 3, 50, '11:45', '12:15' 
    UNION 
    SELECT 4, 50, '12:15', '13:40' 
    UNION 
    SELECT 5, 50, '14:00', '14:40' 
    UNION 
    SELECT 6, 50, '14:40', '15:10' 
    UNION 
    SELECT 7, 50, '15:10', '18:00' 


SELECT 
    A.EMP_ID, A.START_TIME, A.END_TIME, 
    B.START_TIME, B.END_TIME 
FROM 
    @EMP_DETAILS A 
LEFT JOIN 
    @EMP_DETAILS B ON A.END_TIME = B.START_TIME 
        AND A.EMP_ID = B.EMP_ID 

私の期待される出力は次のようになります。

EMP_ID START_TIME END_TIME RN 
--------------------------------- 
50  09:30  10:30  1 
50  10:30  11:45  1 
50  11:45  12:15  1 
50  14:00  14:40  2 
50  14:40  15:10  2 

私は希望を持って、あなたは私が言うことをしようとしていますかについて明確にしています。..

ありがとうございます。

+1

**どのSQL Serverバージョン**を使用していますか? SQL Server ** 2008 **の時点では、適切な* TIMEデータ型があります。すべてを文字列に絞るのではなく、常に最も適切なデータ型を使用する必要があります。 –

答えて

0

シンプル:不要な行を除く

select sq.EMP_ID, sq.START_TIME, sq.END_TIME, sq.RN 
from (
    select e.*, 
    sum(case when xt.ID is not null then 0 else 1 end) 
    over(partition by e.emp_id order by e.start_time) + 1 as [RN], 
    xt.ID as [SameRange] 
    from @EMP_DETAILS e 
    left join @EMP_DETAILS xt on xt.EMP_ID = e.EMP_ID and xt.START_TIME = e.END_TIME 
     and xt.ID != e.ID 
) sq 
where sq.SameRange is not null; 

は簡単で、簡単なleft joinで行うことができます。しかし、それらに番号を付けることはやや難解です。稼働合計(sum(...) over(order by ...))が動作するには、SQL Server 2012以降のバージョンが必要です。

テーブルに重複またはゼロ間隔(つまり、同じ行内にstart_time = end_time)が含まれている場合にのみ、この問題が発生する可能性があります。おそらく、テーブルを別の値を提供するサブクエリで置き換える必要があります。

0

RNの列を1つのクエリで計算する方法はありますが、今は考えることができません。カーソルを使用して、次のことがしたいだけで何作成しますので、:

DECLARE @EMP_DETAILS TABLE (
    ID INT, 
    EMP_ID INT, 
    START_TIME VARCHAR(10), 
    END_TIME VARCHAR(10) 
) 
DECLARE @OUTPUT TABLE (
    ID INT, 
    EMP_ID INT, 
    START_TIME VARCHAR(10), 
    END_TIME VARCHAR(10), 
    RN INT NULL 
) 

INSERT INTO @EMP_DETAILS VALUES 
(1, 50, '09:30', '10:30'), 
(2, 50, '10:30', '11:45'), 
(3, 50, '11:45', '12:15'), 
(4, 50, '12:15', '13:40'), 
(5, 50, '14:00', '14:40'), 
(6, 50, '14:40', '15:10'), 
(7, 50, '15:10', '18:00') 

INSERT INTO @OUTPUT 
SELECT A.ID, A.EMP_ID, A.START_TIME, A.END_TIME, NULL 
FROM @EMP_DETAILS A 
     INNER JOIN @EMP_DETAILS B ON A.EMP_ID = B.EMP_ID AND A.END_TIME = B.START_TIME 

DECLARE @ID INT, @I INT, @J INT = 1 

SELECT @I = MIN(ID) - 1 
FROM @OUTPUT 

DECLARE CR CURSOR LOCAL FOR 
    SELECT ID 
    FROM @OUTPUT 
    ORDER BY ID 

OPEN CR 
FETCH NEXT FROM CR INTO @ID 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF @ID > @I + 1 
    SET @J = @J + 1 

    UPDATE @OUTPUT 
    SET RN = @J 
    WHERE ID = @ID 

    SET @I = @ID 

    FETCH NEXT FROM CR INTO @ID 
END 

CLOSE CR 
DEALLOCATE CR 

SELECT EMP_ID, START_TIME, END_TIME, RN 
FROM @OUTPUT 
ORDER BY ID 

代わりのLEFT JOINをやって、私は不要な行を排除した、INNER JOINを使用しました。その後、RN列は、テーブル内のレコードをCURSORで移動してIDシーケンスの中断を見つけることによって計算されました。休憩があった場合は、RNをインクリメントします。これは、IDが実際のデータに欠損番号を持つことはないと仮定しています。

これは、上記のクエリからの出力である:

EMP_ID  START_TIME END_TIME RN 
----------- ---------- ---------- ----------- 
50   09:30  10:30  1 
50   10:30  11:45  1 
50   11:45  12:15  1 
50   14:00  14:40  2 
50   14:40  15:10  2 
関連する問題