SQL Server查询:消除辅助表列的午夜时间间隔

时间:2017-04-03 18:14:16

标签: sql sql-server time

我想在午夜时间间隔消除辅助表列,即:

使用辅助表格列:

#textarea-container textarea {
height: 4em!important;
transition: all 0.5s ease!important;
box-sizing: border-box;
overflow-y: auto;
resize: none;
}

#textarea-container {
position: relative;
}
#textarea-button {
position: absolute;
top: 3px;
right: 0;
}

没有辅助表格列:

timeIsValidFrom1    00:00:00
timeIsValidTo1      06:00:00
timeIsValidFrom2    18:00:00
timeIsValidTo2      00:00:00

但如果我查询:

timeIsValidFrom    18:00:00
timeIsValidTo      06:00:00

我得到了这个结果:

SELECT 
    cdr.*,
    tariff.*
FROM 
    AAA_Cdr AS cdr  
LEFT JOIN 
    AAA_Pricelists AS tariff ON ((cdr.timCallStarts >= timeIsValidFrom 
                             AND cdr.timCallStarts < tariff.timeIsValidTo));

问题是第2行和第3行返回NULL而不是“人工时间间隔”而不返回空闲时间

SQL Server中是否有任何功能可以在午夜时间间隔内工作?

谢谢你,最诚挚的问候,

彼得

示例结构:

1   2017-04-01  11:30:00.0000000    11:35:15.0000000    1   Worktime    06:00:00.0000000    18:00:00.0000000
2   2017-04-01  18:45:02.0000000    18:46:05.0000000    NULL    NULL    NULL    NULL
3   2017-04-01  03:45:02.0000000    03:46:05.0000000    NULL    NULL    NULL    NULL
4   2017-04-01  14:30:00.0000000    14:35:15.0000000    1   Worktime    06:00:00.0000000    18:00:00.0000000

评论更新:我想要这个结果:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[AAA_Cdr]
(
    [intCdrId] [int] IDENTITY(1,1) NOT NULL,
    [dateInitialedDay] [date] NULL,
    [timCallStarts] [time](7) NULL,
    [timCallFinished] [time](7) NULL,

    CONSTRAINT [PK_AAA_Cdr] 
        PRIMARY KEY CLUSTERED ([intCdrId] ASC)
) ON [PRIMARY]

CREATE TABLE [dbo].[AAA_Pricelists]
(
    [intPricelistId] [int] IDENTITY(1,1) NOT NULL,
    [strName] [nvarchar](50) NULL,
    [timeIsValidFrom] [time](7) NULL,
    [timeIsValidTo] [time](7) NULL,

    CONSTRAINT [PK_AAA_Pricelists] 
        PRIMARY KEY CLUSTERED ([intPricelistId] ASC)
) ON [PRIMARY]
GO

SET IDENTITY_INSERT [dbo].[AAA_Cdr] ON 
GO
INSERT [dbo].[AAA_Cdr] ([intCdrId], [dateInitialedDay], [timCallStarts], [timCallFinished]) 
VALUES (1, CAST(N'2017-04-01' AS Date), CAST(N'11:30:00' AS Time), CAST(N'11:35:15' AS Time))
GO

INSERT [dbo].[AAA_Cdr] ([intCdrId], [dateInitialedDay], [timCallStarts], [timCallFinished]) 
VALUES (2, CAST(N'2017-04-01' AS Date), CAST(N'18:45:02' AS Time), CAST(N'18:46:05' AS Time))
GO

INSERT [dbo].[AAA_Cdr] ([intCdrId], [dateInitialedDay], [timCallStarts], [timCallFinished]) 
VALUES (3, CAST(N'2017-04-01' AS Date), CAST(N'03:45:02' AS Time), CAST(N'03:46:05' AS Time))
GO

INSERT [dbo].[AAA_Cdr] ([intCdrId], [dateInitialedDay], [timCallStarts], [timCallFinished]) 
VALUES (4, CAST(N'2017-04-01' AS Date), CAST(N'14:30:00' AS Time), CAST(N'14:35:15' AS Time))
GO

SET IDENTITY_INSERT [dbo].[AAA_Cdr] OFF
GO

SET IDENTITY_INSERT [dbo].[AAA_Pricelists] ON 
GO

INSERT [dbo].[AAA_Pricelists] ([intPricelistId], [strName], [timeIsValidFrom], [timeIsValidTo]) 
VALUES (1, N'Worktime', CAST(N'06:00:00' AS Time), CAST(N'18:00:00' AS Time))
GO

INSERT [dbo].[AAA_Pricelists] ([intPricelistId], [strName], [timeIsValidFrom], [timeIsValidTo]) 
VALUES (2, N'Freetime', CAST(N'18:00:00' AS Time), CAST(N'06:00:00' AS Time))
GO

SET IDENTITY_INSERT [dbo].[AAA_Pricelists] OFF
GO

Example

1 个答案:

答案 0 :(得分:0)

让我们来看看你的这部分问题:

cdr.timCallStarts >= timeIsValidFrom AND cdr.timCallStarts < tariff.timeIsValidTo

为简单起见,我将其重写为:startOfRange <= testValue AND testValue < endOfRange

由于所有这些都是仅限时间的值,您需要考虑在24小时循环时钟上建模的时间,而不是在线性时间轴上。一旦你进行了这种心理转换,你就可以轻松处理午夜时间范围。

逻辑值:

if startOfRange <= endOfRange
    startOfRange <= testValue AND testValue < endOfRange
else
    startOfRange <= testValue OR testValue < endOfRange

基本上,当值不按顺序时,我们假设它们越过午夜,因此我们只关心值是否在开始之后(隐含地在午夜之前)或者如果值在结束之前(隐含地在午夜之后)。

将其翻译回您的SQL:

SELECT cdr.*, tariff.*
FROM AAA_Cdr AS cdr
LEFT JOIN AAA_Pricelists AS tariff ON (
    timeIsValidFrom <= tariff.timeIsValidTo AND
    (cdr.timCallStarts >= timeIsValidFrom AND cdr.timCallStarts < tariff.timeIsValidTo)
) OR (
    timeIsValidFrom > tariff.timeIsValidTo AND
    (cdr.timCallStarts >= timeIsValidFrom OR cdr.timCallStarts < tariff.timeIsValidTo)
)