从同一个表中连接记录

时间:2014-04-04 21:15:13

标签: sql sql-server

有一个表测试,其中包含如下所示的数据:

id  id1 id2 id3     date1
1   1   2   2500    2010-09-30 00:00:00.000
2   1   2   4700    2005-01-01 00:00:00.000
3   1   2   4700    2009-08-01 00:00:00.000
4   1   3   2500    2010-09-30 00:00:00.000
5   1   3   4700    2003-02-01 00:00:00.000
6   1   8   4000    2007-04-01 00:00:00.000
7   1   8   4000    2013-09-01 00:00:00.000
8   1   8   4060    2007-04-01 00:00:00.000
9   1   8   8500    2010-09-30 00:00:00.000

我需要做的是按以下格式订购此数据:

id1 id2 id3     date1                   date2
1   2   2500    2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1   2   4700    2005-01-01 00:00:00.000 2009-07-31 00:00:00.000
1   2   4700    2009-08-01 00:00:00.000 9999-12-31 23:59:59.997
1   3   2500    2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1   3   4700    2003-02-01 00:00:00.000 9999-12-31 23:59:59.997
1   8   4000    2007-04-01 00:00:00.000 2013-08-31 00:00:00.000
1   8   4000    2013-09-01 00:00:00.000 9999-12-31 23:59:59.997
1   8   4060    2007-04-01 00:00:00.000 9999-12-31 23:59:59.997
1   8   8500    2010-09-30 00:00:00.000 9999-12-31 23:59:59.997

使用以下逻辑:

  • 如果同一个id1,id2和id3只有一条记录,我们使用date1的原始日期,我们使用sql server(9999-12-31)中可用的最大日期作为date2。
  • 如果同一个id1,id2和id3有多个记录,我们仍保留date1的原始日期,我们将date2用作原始日期字段减去下一条记录的1天。最后一条记录还将使用sql server(9999-12-31)中date2的最大日期。

我设法构建以下查询,但它不完美,因为它带来了一些无效的记录:

select * from 
(select 
t1.id1,t1.id2,t1.id3,t1.date1,
case
when t1.date1=t2.date1 then CONVERT(DATETIME, '12/31/9999 23:59:59.997')
else DATEADD(day, -1, t2.date1)
end as date2
from test t1
inner join test t2
on t1.id1=t2.id1 and t1.id2=t2.id2 and t1.id3=t2.id3
) sub
where date2>=date1 
order by id1,id2,id3,date1 asc

查询结果为:

id1 id2 id3     date1                   date2
1   2   2500    2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1   2   4700    2005-01-01 00:00:00.000 9999-12-31 23:59:59.997 *
1   2   4700    2005-01-01 00:00:00.000 2009-07-31 00:00:00.000
1   2   4700    2009-08-01 00:00:00.000 9999-12-31 23:59:59.997
1   3   2500    2010-09-30 00:00:00.000 9999-12-31 23:59:59.997
1   3   4700    2003-02-01 00:00:00.000 9999-12-31 23:59:59.997
1   8   4000    2007-04-01 00:00:00.000 9999-12-31 23:59:59.997 *
1   8   4000    2007-04-01 00:00:00.000 2013-08-31 00:00:00.000
1   8   4000    2013-09-01 00:00:00.000 9999-12-31 23:59:59.997
1   8   4060    2007-04-01 00:00:00.000 9999-12-31 23:59:59.997
1   8   8500    2010-09-30 00:00:00.000 9999-12-31 23:59:59.997

正如您所看到的,标有*的记录不是必需的,但我不知道如何摆脱这些行。

2 个答案:

答案 0 :(得分:0)

尝试这样的事情

SELECT t1.id1, t1.id2, t1.id3, t1.date1 as date1,
    ISNULL(t2.date1, CONVERT(DATETIME, '12/31/9999 23:59:59.997')) as date2
FROM test t1
    LEFT JOIN test t2 ON t1.id1 = t2.id1 AND t1.id2 = t2.id2 AND t1.id3 = t2.id3
        AND t1.id < t2.id
ORDER BY t1.id1, t1.id2, t1.id3, date1, date2

答案 1 :(得分:0)

这应该做:

select id1,id2,id3, date1, 
isnull(lead(date1) over(partition by id1,id2,id3 order by date1)-1, '99991231') as date2
from test