T-SQL combine periods

时间:2015-06-30 13:36:57

标签: sql sql-server database tsql

here is the example table with data (rn column is ROW_NUMBER() for each UELN).

UELN            OwnerID Date                    rn
191001180010389 017581  1989-06-30 00:00:00.000 1
191001180010389 017747  2011-06-02 00:00:00.000 2
191001180010389 017992  2014-03-25 00:00:00.000 3
191001180010389 117030  2015-02-03 00:00:00.000 4
191001250009303 018148  2004-06-30 00:00:00.000 1
191001250009303 018418  2013-10-16 00:00:00.000 2

I need to combine those rows to get result set like this:

UELN            OwnerID DateFrom                DateTo
191001180010389 017581  1989-06-30 00:00:00.000 2011-06-02 00:00:00.000
191001180010389 017747  2011-06-02 00:00:00.000 2014-03-25 00:00:00.000
191001180010389 017992  2014-03-25 00:00:00.000 2015-02-03 00:00:00.000
191001180010389 117030  2015-02-03 00:00:00.000 NULL
191001250009303 018148  2004-06-30 00:00:00.000 2013-10-16 00:00:00.000
191001250009303 018418  2013-10-16 00:00:00.000 NULL

NULL in DateTo column means that this is still valid.

Can anyone help me with the query?

4 个答案:

答案 0 :(得分:3)

select u1.*, u2.date as [date to]
from tabl u1  
left join tabl u2 
on u1.UELN  = u2.UELN 
and u2.rn = u1.rn + 1 

You just need a left self join
The left part is what gets the null date for the no match

答案 1 :(得分:2)

Using OUTER APPLY:

SELECT 
    t.UELN,
    t.OwnerID,
    DateFrom = t.[Date],
    DateTo = x.DateTo
FROM tbl t
OUTER APPLY(
    SELECT
        DateTo = [Date]
    FROM tbl
    WHERE
        UELN = t.UELN
        AND rn = t.rn + 1
)x

答案 2 :(得分:0)

You can try the following:

-- Create demo data
CREATE TABLE #temp(ueln bigint, ownerid nvarchar(20), date date, rn int)

INSERT INTO #temp(ueln, ownerid, date, rn)
VALUES  (191001180010389,N'017581', N'1989-06-30 00:00:00.000', 1),
        (191001180010389,N'017747', N'2011-06-02 00:00:00.000', 2),
        (191001180010389,N'017992', N'2014-03-25 00:00:00.000', 3),
        (191001180010389,N'117030', N'2015-02-03 00:00:00.000', 4),
        (191001250009303,N'018148', N'2004-06-30 00:00:00.000', 1),
        (191001250009303,N'018148', N'2013-10-16 00:00:00.000', 2)

-- your part
SELECT cur.ueln, cur.ownerid, cur.date as date_from, due.date as date_to
    -- Maybe 1 day befor: DATEADD(day,-1,due.date) as date_to
FROM #temp as cur
LEFT JOIN #temp as due
        ON cur.ueln = due.ueln
        AND cur.rn = due.rn+1

DROP TABLE #temp

Which results in:

ueln                 ownerid              date_from  date_to
-------------------- -------------------- ---------- ----------
191001180010389      017581               1989-06-30 NULL
191001180010389      017747               2011-06-02 1989-06-30
191001180010389      017992               2014-03-25 2011-06-02
191001180010389      117030               2015-02-03 2014-03-25
191001250009303      018148               2004-06-30 NULL
191001250009303      018148               2013-10-16 2004-06-30

If you want to be the date_to one day before the next data-row, you can use the commented date_to.

答案 3 :(得分:0)

我们可以使用SQL 2012中引入的LEAD()函数。

--setup
CREATE TABLE #temp(ueln bigint, ownerid nvarchar(20), [date] date)

INSERT INTO #temp(ueln, ownerid, [date])
VALUES  (191001180010389, N'017581', N'1989-06-30 00:00:00.000'),
        (191001180010389, N'017747', N'2011-06-02 00:00:00.000'),
        (191001180010389, N'017992', N'2014-03-25 00:00:00.000'),
        (191001180010389, N'117030', N'2015-02-03 00:00:00.000'),
        (191001250009303, N'018148', N'2004-06-30 00:00:00.000'),
        (191001250009303, N'018148', N'2013-10-16 00:00:00.000');

--actual query
SELECT [ueln] ,
       [ownerid] ,
       [date] AS [DateFrom]
    , LEAD([date], 1) OVER (PARTITION BY ueln ORDER BY [date]) AS [DateTo]
FROM #temp

感谢@Ionic的临时表定义!