解决日期间隔交叉点

时间:2014-04-30 12:47:20

标签: sql-server tsql

我们有一个表格

  • 颜色名称
  • 此颜色使用月份的开头编号和结束编号
  • 数据库中的上诉顺序

创建表格:

create table colorTimes (iOrder int, color varchar(10), pStart int, pEnd int) 

现在我们要在其中输入一些颜色数据:

insert into colorTimes (iOrder, color, pStart, pEnd) values (1, 'green', 2, 12)
insert into colorTimes (iOrder, color, pStart, pEnd) values (2, 'blue', 4, 4)
insert into colorTimes (iOrder, color, pStart, pEnd) values (3, 'red', 9, 10)
insert into colorTimes (iOrder, color, pStart, pEnd) values (4, 'yellow', 6, 7)
insert into colorTimes (iOrder, color, pStart, pEnd) values (5, 'orange', 1, 2)
insert into colorTimes (iOrder, color, pStart, pEnd) values (6, 'violet', 7, 9)

规则是具有更高iOrder值的颜色具有更高的优先级并且重叠 通过将它们剪切到需要适合自己的值的较低优先级颜色间隔。 当一个较新的行落在更旧的行的中心时,它将它切成两块。 因此,我们需要执行一些操作以正确的形式获取此表中的数据 - 没有交叉点保持此规则。从图形上看,它看起来像是:enter image description here

输入:

enter image description here

必需的输出:

enter image description here

正如您在结果中看到的那样,代表绿线的行被其他人划分为三行 并且在某些时间间隔内仍然有效。

这个高度抽象的示例隐藏了与数据交互的问题,存储方式如Value \ DateBegin \ DateEnd 它的分区和交叉点。 主要目标是只获得一个代表一定时间的价值(即我们需要知道 哪个颜色是第8个月):

select color from colorTimes where 8 between pStart and pEnd

enter image description here

在某些情况下,我们无法:

  • 输入初始数据时使用厚脸皮的触发器。
  • 使用初始数据更改任何工作逻辑,以及通过初始数据获取它的方法 应用程序(它每次使用相同的选择,并期望只看到一个值)。
  • 更改数据存储的方式。

1 个答案:

答案 0 :(得分:2)

DML脚本的Thx。

以下是我将如何做到这一点(SQL Server 2012 +):

;with x as (
    select *,
    row_number() over(partition by n order by iorder desc) as rn
    from colortimes c
    inner join numbers n on n.n between c.pstart and c.pend
),
y as (
    select distinct iOrder, color, n, 
        lead(color) over (order by n) as lead_color,
        isnull(lag(n) over(order by n), 0) + 1 as pend
    from x
    where rn = 1
),
z as (
    select *,       
        isnull(lag(n) over(order by n), 0) + 1 as pstart
    from y
    where color <> lead_color or lead_color is null
)
select iorder, color, pstart, pend
from z
--where 8 between pstart and pend
order by n

关于numbers table

相关问题