如果日期是连续的并且键值相同,则合并两个记录日期

时间:2014-10-24 21:20:43

标签: sql sql-server tsql date

我有两种不同的情景。在第一个场景中,我需要类似的东西:

create table test
(
ItemID int,
ItemStartDate datetime,
ItemEndDate datetime,
itemType varchar(100)
)

test

ItemID  ItemStartDate  ItemEndDate  itemType
------  -------------  -----------  --------
item_1  1/1/2011       3/2/2011     value A
item_1  3/3/2011       12/31/2011   value A
item_2  1/3/2011       12/31/2011   value B

它应该只显示两条记录:

ItemID  ItemStartDate  ItemEndDate  itemType
------  -------------  -----------  --------
item_1  1/1/2011       12/31/2011   value A
item_2  1/1/2011       12/31/2011   value B

情景2。 在这里,我想将数据值拆分为单独的年份,如果它是多年的话。

test

create table #Scenario_2
(
ItemID int,
priceStartDate datetime,
priceEndDate datetime,
price int
)

item  startdate  enddate     value
----  ---------  ----------  -----
11    1/1/2011   5/4/2013    500
12    7/1/2013   11/12/2013  600

它应该显示为

item  startdate  enddate     value
----  ---------  ----------  -----
11    1/1/2011   12/31/2011  500
11    1/1/2012   12/31/2012  500
11    1/1/2013   5/4/2013    500
12    7/1/2013   11/12/2013  600

请告知我如何实现这一目标。

2 个答案:

答案 0 :(得分:1)

试试这个。从你的问题来看,这就是我所理解的!!

SCENARIO 2
----------
CREATE TABLE #datt
  (
     itemid   int,startd DATE,endat  DATE,price int
  )

INSERT INTO #datt
VALUES      (11,'2011-01-01','2013-05-04',500),
            (12,'2013-7-1','2013-11-12',600)

;WITH cte
     AS (SELECT itemid,
                 startd st,
                case when year(endat)<> YEAR(startd) then Dateadd(yy, Year(startd) - 1899, -1)
                else endat end ed,price
         FROM   #datt
         UNION ALL
         SELECT a.itemid,
                Dateadd(yy, 1, st),
                CASE
                  WHEN Dateadd(yy, 1, ed) > b.endat THEN b.endat
                  ELSE Dateadd(yy, 1, ed)
                END,a.price
         FROM   cte a
                JOIN #datt b
                  ON a.itemid = b.itemid
                     AND a.ed < b.endat)
SELECT *
FROM   cte order by itemid,st

答案 1 :(得分:0)

对于scenario1,您可以看到this answer

对于scenario2,还可以引用similar answer

但你的问题可以像这样简化:

with dates as
(
select number,cast(ltrim(number*10000+1231) as date) as dt
    from master..spt_values
    inner join 
        (select min(year(startdate)) as s_year
               ,max(year(enddate))  as e_year
         from Scenario_2) as y
    on number between y.s_year and y.e_year AND TYPE='P'
)
select 
    s.item
   ,case when year(dt) = year(startdate) 
         then startdate
         else dateadd(year,-1,dateadd(day,1,dt)) end  --or cast(ltrim(year(dt)*10000+101) as date)
   ,case when year(dt) = year(enddate)
         then enddate
         else dt end
   ,s.value
from 
    Scenario_2 s
inner join 
    dates d
on 
    d.number between year(s.startdate) and year(s.enddate)

SQL FIDDLE DEMO