2017-04-03 75 views
0

间隔辅助表列,我想消除辅助表列午夜前后间隔,即:SQL Server查询:消除子夜时分

随着辅助表列:

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

没有辅助表列:

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

b UT如果我做一个查询:

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

我得到这样的结果:

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 

的问题是2和3行返回NULL,而不是“人的时间间隔”不回免费时间

SQL Server中有没有可以在午夜时间间隔内使用的函数?

谢谢你,最好的问候,

切赫

结构示例:

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 

更新通过评论:我想这个结果:

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 2 Freetime 18:00:00.0000000 06:00:00.0000000 
3 2017-04-01 03:45:02.0000000 03:46:05.0000000 2 Freetime 18:00:00.0000000 06:00:00.0000000 
4 2017-04-01 14:30:00.0000000 14:35:15.0000000 1 Worktime 06:00:00.0000000 18:00:00.0000000 

Example

+0

这样一个伟大的工作,张贴DDL和样本数据。我正在努力了解您希望从此示例数据中输出的内容。你能清楚地解释你想作为输出吗? –

+0

我按部分更新问题的结尾:“通过评论更新:我想要这个结果” – czWolfHunter

+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) 
)