2

我有像这样的表结构

ATM         Ticket Open Time    Ticket Closed Time

M30G324202  17-02-2013 06:15    19-02-2013 20:54
M30G324202  28-02-2013 21:00    01-03-2013 11:18
M30G324203  27-02-2013 19:10    28-02-2013 07:14
M30G324203  28-02-2013 07:15    28-02-2013 11:18

如果票务开放时间或票务关闭时间介于“20:00:00”和“06:00:00”之间,即晚上 8 点和早上 6 点,则应创建没有该时间范围的新行

例如上表的第一行

ATM         Ticket Open Time    Ticket Closed Time

M30G324202  17-02-2013 06:15    17-02-2013 20:00
M30G324202  18-02-2013 06:00    18-02-2013 20:00
M30G324202  19-02-2013 06:00    19-02-2013 20:00

//Above was for Only 1st Row

//Second Row Change AS Follows

M30G324202  01-03-2013 06:00    01-03-2013 11:18 
   (Time From 28-02-2013 21:00 Will get neglected till next day morning 6 AM 
    as it is after 8 PM )

//Third Row Change AS Follows

M30G324203  27-02-2013 19:10    27-02-2013 20:00
M30G324203  28-02-2013 06:00    28-02-2013 07:14

//Fourth Row Change AS Follows

M30G324203  28-02-2013 07:15    28-02-2013 11:18 (No Change as it is)

我写20:00了而不是20:54因为 54 分钟。2 月 19 日晚上 8 点以后。

4

2 回答 2

2

您可以使用递归 CTE 执行此操作。以下代码显示了如何。对于 CTE 中的测试数据A,使用类似

SELECT ATM, [Ticket Open Time], [Ticket Close Time] FROM Table1

测试数据在这里表明所有情况都已处理完毕。如果您不希望包含 ATM = W 的情况,或者您想调整开始日期,您可以相应地修改 SQL。

此外,我使用了一种老式技术来获取datetime. 同样,根据您使用的 SQL Server 版本进行调整。

WITH A
AS  (

    SELECT 'X' as ATM
        ,   convert(datetime, '2/17/2013 6:15') as [Ticket Open Time]
        ,   convert(datetime, '2/19/2013 20:54') as [Ticket Close Time]
    UNION ALL 
    SELECT  'Y'
        ,   convert(datetime, '2/24/2013 7:32')
        ,   convert(datetime, '2/25/2013 14:26')
    UNION ALL
    SELECT  'Z'
        ,   convert(datetime, '2/20/2013 9:00')
        ,   convert(datetime, '2/20/2013 13:43')    
    UNION ALL
    SELECT  'W'
        ,   convert(datetime, '3/1/2013 3:34')
        ,   convert(datetime, '3/1/2013 6:45')  
)
,   B
AS  (

    SELECT  ATM
        ,   [Ticket Open Time]
        ,   [Original Ticket Close Time] = A.[Ticket Close Time]
        ,   [Ticket Close Time] = CASE WHEN  DateAdd(hh, 20, convert(datetime, convert(varchar(10), [Ticket Open Time], 101))) > A.[Ticket Close Time]
                 THEN  [Ticket Close Time]
                 ELSE  DateAdd(hh, 20, convert(datetime, convert(varchar(10), [Ticket Open Time], 101)))
            END
    FROM    A
    UNION ALL
    SELECT  ATM
        ,   [Ticket Open Time] = DateAdd(hh, 10, B1.[Ticket Close Time])
        ,   [Original Ticket Close Time] = b1.[Original Ticket Close Time]
        ,   [Ticket Close Time] = CASE
                WHEN DateAdd(hh, 24, b1.[Ticket Close Time]) > b1.[Original Ticket Close Time]
                AND  b1.[Original Ticket Close Time] <= DateAdd(hh,24, b1.[Ticket Close Time])
                THEN b1.[Original Ticket Close Time]
                ELSE DateAdd(hh, 24, b1.[Ticket Close Time])
            END
    FROM    B b1
    WHERE   [Ticket Close Time] < b1.[Original Ticket Close Time]

)
,   C
as  (
    select *
    from    B
    where   [Ticket Open Time] < [Ticket Close Time]
)   
      -- Your actual output
select    ATM, 
            [Ticket Open Time],
        [Ticket Close Time],
 from     C  
 order by  ATM,
         [Ticket Open Time]
于 2013-05-15T12:48:12.563 回答
1

一个很好的问题! 请检查我的尝试:

declare @tbl as table (ATM nvarchar(20), TicketOpenTime datetime, TicketClosedTime datetime)
insert into @tbl values
('M30G324202', '02-17-2013 06:15', '02-19-2013 20:54'),
('M30G324202', '02-28-2013 21:00', '03-01-2013 11:18'),
('M30G324203', '02-27-2013 19:10', '02-28-2013 07:14'),
('M30G324203', '02-28-2013 07:15', '02-28-2013 11:18')

declare @min datetime, @max datetime
select @min = MIN(TicketOpenTime), @max = max(TicketClosedTime) from @tbl

;with T as(
    select CONVERT(datetime, convert(numeric(20), @min, 101)) dt
    union all
    select dt+1 from T where dt<@max
) 
select 
    a.ATM, 
    case when a.TicketOpenTime>dt1 then a.TicketOpenTime else dt1 end TicketOpenTime,
    case when a.TicketClosedTime>dt2 then dt2 else a.TicketClosedTime end TicketClosedTime
From @tbl a
cross apply(
    select 
        dt, 
        DATEADD(minute, 360, dt) dt1, 
        DATEADD(minute, 1200, dt) dt2 from T b 
    where 
        dt between CAST(a.TicketOpenTime as DATE) and cast(a.TicketClosedTime as DATE)
)x
where a.TicketOpenTime<=x.dt2
order by a.ATM, a. TicketOpenTime
于 2013-05-15T12:55:52.337 回答