-1

次のようなテーブルがあります。

create table time_sheet
(
      StatusCode char(1),
      start_time datetime,
      end_time datetime
)

insert into time_sheet values
('W','2012-08-01 10:00:00','2012-08-01 12:00:00'),
('D','2012-08-01 12:00:00','2012-08-01 14:00:00'),
('N','2012-08-01 16:00:00','2012-08-01 18:00:00')

出力は次のようになります。

StatusCode start_time               end_time
B          2012-08-01 08:00:00.000  2012-08-01 10:00:00.000
W          2012-08-01 10:00:00.000  2012-08-01 12:00:00.000
D          2012-08-01 12:00:00.000  2012-08-01 14:00:00.000
B          2012-08-01 14:00:00.000  2012-08-01 16:00:00.000
N          2012-08-01 16:00:00.000  2012-08-01 18:00:00.000
B          2012-08-01 18:00:00.000  2012-08-01 20:00:00.000

一日の始まりと終わりは以下のように宣言されます。

declare @begingOfDay datetime='2012-08-01 08:00:00.000'
declare @endOfDay    datetime='2012-08-01 20:00:00.000'

基本的には、結果セットのbeginOfDayendOfDayの間のstatusCode Bに欠落している時間範囲レコードが必要です 。出力に、StatusCode B で追加された 3 つのレコードがあることを確認してください。

誰でもこれを手伝ってもらえますか?

4

2 に答える 2

1

サンプル データ (T明確な日付変換を強制するために文字列に s が追加されていることに注意してください):

create table time_sheet
(
      StatusCode char(1),
      start_time datetime,
      end_time datetime
)

insert into time_sheet values
('W','2012-08-01T10:00:00','2012-08-01T12:00:00'),
('D','2012-08-01T12:00:00','2012-08-01T14:00:00'),
('N','2012-08-01T16:00:00','2012-08-01T18:00:00')

declare @begingOfDay datetime='2012-08-01T08:00:00.000'
declare @endOfDay    datetime='2012-08-01T20:00:00.000'

そしてクエリ:

;with AllDTs as (
    select @begingOfDay as TimePoint
    union
    select @endOfDay
    union
    select start_time from time_sheet
    union
    select end_time from time_sheet
), OrderedDTs as (
    select TimePoint,ROW_NUMBER() OVER (ORDER BY TimePoint) as rn
    from AllDTs
), Periods as (
    select o1.TimePoint as start_time,o2.TimePoint as end_time
    from
        OrderedDTs o1
            inner join
        OrderedDTs o2
            on
                o1.rn = o2.rn-1
)
select
    COALESCE(ts.StatusCode,'B') as StatusCode,
    p.start_time,
    p.end_time
from
    Periods p
        left join
    time_sheet ts
        on
            p.start_time = ts.start_time and
            p.end_time = ts.end_time

結果:

StatusCode start_time              end_time
---------- ----------------------- -----------------------
B          2012-08-01 08:00:00.000 2012-08-01 10:00:00.000
W          2012-08-01 10:00:00.000 2012-08-01 12:00:00.000
D          2012-08-01 12:00:00.000 2012-08-01 14:00:00.000
B          2012-08-01 14:00:00.000 2012-08-01 16:00:00.000
N          2012-08-01 16:00:00.000 2012-08-01 18:00:00.000
B          2012-08-01 18:00:00.000 2012-08-01 20:00:00.000

元のテーブルに重複する期間がないことを前提に進めたことに注意してください。最初の CTE ( AllDTs) は、関心のあるすべての一意の日時値を見つけるだけです。OrderedDTsそしてPeriods、これらすべての日時値を連続する期間に配置します。最後のクエリは、これらの各ピリオドを取得し、可能であれば元のテーブルと照合しようとします。そうでない場合は、明らかにB期間です。

于 2012-08-01T12:20:33.473 に答える
1

これを試してください:

declare @begingOfDay datetime='2012-08-01 08:00:00.000'
declare @endOfDay    datetime='2012-08-01 20:00:00.000'




 declare @begingOfDay datetime='2012-08-01 08:00:00.000'
declare @endOfDay    datetime='2012-08-01 20:00:00.000'


;WITH CTEMain as (select ROW_NUMBER() over (order by (select 0)) as id,StatusCode,start_time,end_time from time_sheet)

,CTE2 as (
select * from (

select    CASE WHEN start_time > @begingOfDay then 'B' else StatusCode end as statusCode,
          CASE WHEN start_time > @begingOfDay then @begingOfDay else start_time end as start_time,
          CASE WHEN start_time > @begingOfDay then start_time else end_time end as end_time
          FROM CTEMain where id=1
UNION
select StatusCode,start_time,end_time from CTEMain 
union 

select 'B'
       ,CASE WHEN CAST(((select c.start_time from CTEMain c where c.id=t1.id+1)-t1.end_time) as time) > '00:00:00' then end_time  else null end as start_time
       ,CASE WHEN CAST(((select c.start_time from CTEMain c where c.id=t1.id+1)-t1.end_time) as time) > '00:00:00' then end_time+((select c.start_time from CTEMain c where c.id=t1.id+1)-t1.end_time)  else null end as start_time
     from CTEMain t1


     ) a)

select * from (  
select * from CTE2 where start_time is not null
union all
select 'B',CASE WHEN MAX(end_time) = @endOfDay then null else  MAX(end_time) end as start_time,@endOfDay as end_time from CTE2) a order by start_time 
于 2012-08-02T07:49:29.013 に答える