我想基于有序列表生成累积信息。 在下面的例子中,我想基于其他3列生成下雨天。 所以按城镇和白天订购,如果天气干燥则给出零,如果天气下雨则给出累积分数。
程序上这很容易,但感觉应该有一种方法可以直接用sql生成它而我无法理解它。
可能你可以使用分析范围窗口,但我无法弄清楚如何跨3列进行分析。如果存在干扰行则需要重置意味着我不能忽略'干'行并只使用row_number()。
town day weather days of rain
Stevenage 1 dry
Stevenage 2 dry
Stevenage 3 rain 1
Stevenage 4 rain 2
Stevenage 4 rain 3
Stevenage 5 dry
Stevenage 6 dry
Stevenage 8 rain 1
Stevenage 9 rain 2
Stevenage 10 dry
Watford 1 dry
Watford 2 dry
Watford 3 rain 1
Watford 4 rain 2
create table rain_test (town varchar2(20), day number, weather varchar2(10), days_of_rain number);
insert into rain_test(town, day, weather) values ('Stevenage', 1, 'dry');
insert into rain_test(town, day, weather) values ('Stevenage', 2, 'rain');
insert into rain_test(town, day, weather) values ('Stevenage', 3, 'rain');
insert into rain_test(town, day, weather) values ('Stevenage', 4, 'rain');
insert into rain_test(town, day, weather) values ('Stevenage', 5, 'dry');
insert into rain_test(town, day, weather) values ('Stevenage', 6, 'dry');
insert into rain_test(town, day, weather) values ('Stevenage', 7, 'rain');
insert into rain_test(town, day, weather) values ('Stevenage', 8, 'rain');
insert into rain_test(town, day, weather) values ('Stevenage', 9, 'rain');
insert into rain_test(town, day, weather) values ('Stevenage', 10, 'dry');
insert into rain_test(town, day, weather) values ('Watford', 1, 'dry');
insert into rain_test(town, day, weather) values ('Watford', 2, 'dry');
insert into rain_test(town, day, weather) values ('Watford', 3, 'rain');
insert into rain_test(town, day, weather) values ('Watford', 4, 'rain');
commit;
答案 0 :(得分:1)
使用分析功能,
with x as (
select town,
day,
weather,
case when weather = --lag function to find out when the weather changes.
lag(weather,1) over (partition by town order by day)
then 0
else 1
end boundary
from rain_test
),
y as (
select town, day, weather,
sum(boundary) over (partition by town order by day) grp --Sum function to assign a unique group number to a sequence of same weather.
from x
)
select town, day, weather,
case when weather = 'rain'
then row_number() over (partition by town, grp order by day) --row_number function to assign unique number to each row in a group.
end
from y
order by town, day;
答案 1 :(得分:0)
你去,只是为了挑战,在程序上肯定要容易得多,但不是那么有趣:
select town, day, weather, null days_of_rain
from rain_test
where weather = 'dry'
union
select day.town, day.day, weather, day.day - chain.begin_day + 1 days_of_rain
from rain_test day,
(
select town, chain, sum(begin_day) begin_day, sum(end_day) end_day
from (/* to find the chains of rainy days */
select town, rownum chain, day begin_day, 0 end_day
from (/* to find the begining days */
select rain.town, rain.day
from rain_test rain,
rain_test day
where rain.town = day.town
and rain.weather = 'rain'
and day.day = rain.day - 1
and day.weather = 'dry'
union /* border condition */
select town, min(day) day
from rain_test
where weather = 'rain'
group by town
order by town, day
)
union all
select town, rownum chain, 0 begin_day, day end_day
from (/* to find the ending days */
select rain.town, rain.day
from rain_test rain,
rain_test day
where rain.town = day.town
and rain.weather = 'rain'
and day.day = rain.day + 1
and day.weather = 'dry'
union /* border condition */
select town, max(day) day
from rain_test
where weather = 'rain'
group by town
order by town, day
)
)
group by town, chain
) chain
where chain.town = day.town
and chain.begin_day <= day.day
and chain.end_day >= day.day
order by town, day