Sql server 如何比较SQL Server中的时间段?

Sql server 如何比较SQL Server中的时间段?,sql-server,Sql Server,我有一张表[pricelist] startHour endHour Price 以及另一个包含[actualuse] startDate endDate user 我的数据 价格表: startHour | endHour | price ---------------------------- 00:00 | 07:59 | 10 08:00 | 15:59 | 20 16:00 | 23:59 | 5 实际情况: startDate

我有一张表
[pricelist]

startHour
endHour
Price
以及另一个包含
[actualuse]

startDate
endDate
user
我的数据

价格表

startHour | endHour | price
----------------------------
00:00     | 07:59   | 10
08:00     | 15:59   | 20
16:00     | 23:59   | 5
实际情况

startDate        | endDate         | jobId
-------------------------------------------
12/10/2014 08:30 | 12/10/2014 15:20| 1
12/10/2014 07:30 | 12/10/2014 18:20| 2
12/10/2014 07:30 | 13/10/2014 16:20| 3
12/10/2014 09:30 | 13/10/2014 00:20| 4
我试着为每一个gob获取价格表中所有的行。例如,对于Jobid1,我将获得

startDate        | endDate         | jobId  |price
---------------------------------------------------
12/10/2014 08:30 | 12/10/2014 15:20| 1      |20
对于Jobid2

startDate        | endDate         | jobId  |price
---------------------------------------------------
12/10/2014 07:30 | 12/10/2014 07:59| 2      |10    
12/10/2014 08:00 | 12/10/2014 15:59| 2      |20
12/10/2014 16:00 | 12/10/2014 18:20| 2      |5
对于Jobid3

startDate        | endDate         | jobId  |price
---------------------------------------------------
12/10/2014 07:30 | 12/10/2014 07:59| 3      |10
12/10/2014 08:00 | 12/10/2014 15:59| 3      |20
12/10/2014 16:00 | 12/10/2014 23:59| 3      |5
13/10/2014 00:00 | 13/10/2014 07:59| 3      |10
13/10/2014 08:00 | 13/10/2014 15:59| 3      |20
13/10/2014 16:00 | 13/10/2014 16:20| 3      |5

这里有一个可行的解决方案。我知道光标有点难看,但我必须创建另一个表,其中包含日期范围之间的所有可能日期。您也可以重构一些日期计算(我假设您使用的是
TIME
datatype)


一般的解决方案比你想象的要复杂,因为价格可能会在午夜左右结束。在你们的例子中并没有出现这种情况,但这是一个很大的复杂问题。应该有一个列,用于
join
我认为这并不简单,我需要找到工作中的所有时间段。我需要为联接创建一个计算列。@eyalb对于作业1,价格是20而不是10,对吗?@GordonLinoff也许OP可以接受一个规则/限制,即表priceList中的startHour始终小于endHour。看起来不错,但我正在处理mssql 2000,但想法是一样的,我将尝试解决它,对此我不知道。我想你必须用CASE-WHEN和CAST*AS-DATE(去掉时间部分)来替换IIF,以转换成另一个
/*
create table pricelist
(
    startHour time,
    endHour time,
    price decimal(18,2)
)

create table actualuse
(
    startDate datetime,
    endDate datetime,
    jobId int
)

insert pricelist values
('00:00','07:59',10),
('08:00','15:59',20),
('16:00','23:59',5)

set dateformat dmy
insert actualuse values
('12/10/2014 08:30','12/10/2014 15:20',1),
('12/10/2014 07:30','12/10/2014 18:20',2),
('12/10/2014 07:30','13/10/2014 16:20',3),
('12/10/2014 09:30','13/10/2014 00:20',4)

*/

BEGIN TRY DROP TABLE #actualUseDays END TRY
BEGIN CATCH END CATCH

CREATE TABLE #actualUseDays (
    startDate DATETIME
    ,endDate DATETIME
    ,jobId INT
    )

DECLARE @startDate DATETIME
    ,@endDate DATETIME
    ,@jobId INT;

DECLARE cur CURSOR FORWARD_ONLY FOR SELECT * FROM actualuse

OPEN cur;

FETCH NEXT FROM cur INTO @startDate ,@endDate ,@jobId

WHILE @@FETCH_STATUS = 0
BEGIN
    INSERT #actualUseDays
    SELECT @startDate
        ,iif(CAST(@endDate AS DATE) <> CAST(@startDate AS DATE), DATEADD(day, DATEDIFF(day, '19000101', cast(@startDate AS DATE)), CAST(CAST('23:59:59' AS TIME) AS 
                    DATETIME2(7))), @endDate)
        ,@jobId

    UNION

    SELECT CAST(DATEADD(DAY, number + 1, @startDate) AS DATE) [Date]
        ,iif(CAST(@endDate AS DATE) <> CAST(DATEADD(DAY, number + 1, @startDate) AS DATE), DATEADD(day, DATEDIFF(day, '19000101', CAST(DATEADD(DAY, number + 1, 
                            @startDate) AS DATE)), CAST(CAST('23:59:59' AS TIME) AS DATETIME2(7))), @endDate)
        ,@jobId
    FROM master..spt_values
    WHERE type = 'P'
        AND DATEADD(DAY, number + 1, CAST(@startDate AS DATE)) < @endDate

    FETCH NEXT FROM cur INTO @startDate ,@endDate ,@jobId
END

CLOSE cur;
DEALLOCATE cur;

/*
#actualUseDays now contains : 

startDate               endDate                 jobId
----------------------- ----------------------- -----------
2014-10-12 08:30:00.000 2014-10-12 15:20:00.000 1
2014-10-12 07:30:00.000 2014-10-12 18:20:00.000 2
2014-10-12 07:30:00.000 2014-10-12 23:59:59.000 3
2014-10-13 00:00:00.000 2014-10-13 16:20:00.000 3
2014-10-12 09:30:00.000 2014-10-12 23:59:59.000 4
2014-10-13 00:00:00.000 2014-10-13 00:20:00.000 4
*/

SELECT iif(CAST(a.startDate AS TIME) > p.startHour, startDate, DATEADD(day, DATEDIFF(day, '19000101', CAST(startDate AS DATE)), CAST(startHour AS DATETIME2(7)))) AS 
    startDate
    ,iif(CAST(a.endDate AS TIME) < p.endHour, endDate, DATEADD(day, DATEDIFF(day, '19000101', CAST(endDate AS DATE)), CAST(endHour AS DATETIME2(7)))) AS endDate
    ,jobId
    ,price
FROM #actualUseDays a
INNER JOIN pricelist p
    ON CAST(a.startDate AS TIME) <= p.endHour
        AND CAST(a.endDate AS TIME) >= p.startHour
ORDER BY jobId
    ,iif(CAST(a.startDate AS TIME) > p.startHour, startDate, DATEADD(day, DATEDIFF(day, '19000101', CAST(startDate AS DATE)), CAST(startHour AS DATETIME2(7))))
startDate                   endDate                     jobId       price
--------------------------- --------------------------- ----------- ---------------------------------------
2014-10-12 08:30:00.0000000 2014-10-12 15:20:00.0000000 1           20.00
2014-10-12 07:30:00.0000000 2014-10-12 07:59:00.0000000 2           10.00
2014-10-12 08:00:00.0000000 2014-10-12 15:59:00.0000000 2           20.00
2014-10-12 16:00:00.0000000 2014-10-12 18:20:00.0000000 2           5.00
2014-10-12 07:30:00.0000000 2014-10-12 07:59:00.0000000 3           10.00
2014-10-12 08:00:00.0000000 2014-10-12 15:59:00.0000000 3           20.00
2014-10-12 16:00:00.0000000 2014-10-12 23:59:00.0000000 3           5.00
2014-10-13 00:00:00.0000000 2014-10-13 07:59:00.0000000 3           10.00
2014-10-13 08:00:00.0000000 2014-10-13 15:59:00.0000000 3           20.00
2014-10-13 16:00:00.0000000 2014-10-13 16:20:00.0000000 3           5.00
2014-10-12 09:30:00.0000000 2014-10-12 15:59:00.0000000 4           20.00
2014-10-12 16:00:00.0000000 2014-10-12 23:59:00.0000000 4           5.00
2014-10-13 00:00:00.0000000 2014-10-13 00:20:00.0000000 4           10.00