SQL数据范围重叠和偏移

时间:2013-09-04 19:45:43

标签: sql

我有一张如下表格,

Table 
Date1           Date2       Priority    level
1/1/1970    10/31/2013  -1  A
12/1/2013   10/31/2014  -1  A
12/31/2013  1/31/2016   1   B
12/31/2012  10/31/2018  1   C
12/31/2012  10/31/2019  2   C
12/31/2012  12/31/9999  3   C
12/31/2011  12/31/9999  4   C

我需要根据级别和优先级找到重叠和偏移日期范围。 结果

Date1            Date2          level
1/1/1970    10/31/2013  A
12/1/2013   10/31/2014  A
10/31/2014  1/31/2016   B
10/31/2013  12/1/2013   C
1/31/2016   10/31/2019  C
10/31/2019  12/31/9999  C

从视觉上看,这将提供以下内容:

A[---------]-------------------------------------------------------------------------------
A----------------[-----------------]-------------------------------------------------------
B---------------------[------------------]-------------------------------------------------
C--------[----------------------------------------]----------------------------------------
C--------[-------------------------------------------------]-------------------------------
C--------[--------------------------------------------------------------------------------]
C----[------------------------------------------------------------------------------------]

结果

A[---------]-------------------------------------------------------------------------------
A----------------[-----------------]-------------------------------------------------------
B----------------------------------[-----]-------------------------------------------------
C----------[-----]-------------------------------------------------------------------------
C-----------------------------------------[----------------]-------------------------------
C-----------------------------------------------------------[-----------------------------]

1 个答案:

答案 0 :(得分:0)

这里只是一些想法。 SQL在这里小提琴:http://sqlfiddle.com/#!2/f6acc/5

首先,创建一个包含两列的表:

CREATE TABLE [Map] ([Date] datetime, [Level] char(1) NULL)

使用以下内容填充该表:

INSERT [Map]([Date])
SELECT Date1 FROM [Table] UNION
SELECT Date2 FROM [Table]

现在,您的[Map]表包含原始[Table]中的唯一日期列表。现在是时候找出每个日期属于哪个级别了。所以你做了类似的事情:

UPDATE [Map] FROM [Map]
    INNER JOIN [Table] ON [Date] >= [Date1] AND [Date] < [Date2]
SET [Map].[Level] = 'A'
WHERE [Table].[Levle] = 'A' AND [Map].[Level] IS NULL

对每个级别,B,C等重复上述SQL(可能在循环中?)。现在,您的[Map]表按优先顺序包含非重叠间隔:

[Date]      [Level]
1/1/1970    A
12/31/2011  A
12/31/2013  A
10/31/2013  C
12/1/2013   A
12/31/2013
10/31/2014  B
1/31/2016   C
--...and so on

所以我们只需将其转换为您想要的输出形式。我们可以通过扫描[Date] -order中[Map]表的行来获取它,并注意[Level]更改的时间。它可以在一个循环中完成,但是肯定应该有一个很好的SQL方法来实现它,我现在无法绕过它。