今天别人问了我一道复杂的sql面试题, 题目是这样的:
--code 价格 时间
'0010' 100 '2012-08-01 00:00:00.000'
'0010' 100 '2012-08-02 00:00:00.000'
'0010' 100 '2012-08-03 00:00:00.000'
'0010' 100 '2012-08-05 00:00:00.000'
'0012' 120 '2012-08-07 00:00:00.000'
'0012' 120 '2012-08-08 00:00:00.000'
上面是原始数据集,
由上面的数据集,根据时间连续原则, 需要得到下面的结果集
--结果集
--code 价格 开始时间 结束时间
'0010' 100 '2012-08-01' '2012-08-03'
'0010' 100 '2012-08-05' '2012-08-05'
'0012' 120 '2012-08-07' '2012-08-08'
建表语句如下:
CREATE
TABLE
[
dbo
].
[
MyOrder
](
[ code ] [ varchar ]( 10) NULL,
[ price ] [ int ] NULL,
[ time ] [ datetime ] NULL
) ON [ PRIMARY ]
GO
[ code ] [ varchar ]( 10) NULL,
[ price ] [ int ] NULL,
[ time ] [ datetime ] NULL
) ON [ PRIMARY ]
GO
解决代码如下, 一会儿再给你分析我的思路
with cteMinOrder
as
(
select code, MIN(time) as min_time
from MyOrder
group by code
),
cteMyOrder
as
(
SELECT *, Rank()
Over(Partition by code Order BY time) AS rownum
FROM MyOrder
),
cteCompOrder
as
(
select a.code, a.price, a.time, a.rownum,
b.min_time, DATEADD( day, rownum - 1, b.min_time) AS ctime
from cteMyOrder a left join cteMinOrder b
on a.code = b.code
)
select code, price, MIN(time) as start_time, MAX(time) as end_time
from cteCompOrder
where time =ctime
group by code, price
union all
select code, price, MIN(time) as start_time, MAX(time) as end_time
from cteCompOrder
where time !=ctime
group by code, price
order by code
as
(
select code, MIN(time) as min_time
from MyOrder
group by code
),
cteMyOrder
as
(
SELECT *, Rank()
Over(Partition by code Order BY time) AS rownum
FROM MyOrder
),
cteCompOrder
as
(
select a.code, a.price, a.time, a.rownum,
b.min_time, DATEADD( day, rownum - 1, b.min_time) AS ctime
from cteMyOrder a left join cteMinOrder b
on a.code = b.code
)
select code, price, MIN(time) as start_time, MAX(time) as end_time
from cteCompOrder
where time =ctime
group by code, price
union all
select code, price, MIN(time) as start_time, MAX(time) as end_time
from cteCompOrder
where time !=ctime
group by code, price
order by code