我有一张桌子如下。
DATE_WORKED COUNTRY
1-Nov-13 United Kingdom
4-Nov-13 United Kingdom
5-Nov-13 India
6-Nov-13 India
7-Nov-13 India
8-Nov-13 United Kingdom
11-Nov-13 United Kingdom
12-Nov-13 India
13-Nov-13 India
14-Nov-13 India
15-Nov-13 United Kingdom
18-Nov-13 United Kingdom
19-Nov-13 India
20-Nov-13 India
21-Nov-13 India
22-Nov-13 United Kingdom
25-Nov-13 United Kingdom
26-Nov-13 India
27-Nov-13 India
28-Nov-13 India
29-Nov-13 United Kingdom
我希望找到每个国家/地区逗留的start_date和结束日期。
COUNTRY START_DATE END_Date
United Kingdom 1-Nov-13 4-Nov-13
India 5-Nov-13 7-Nov-13
United Kingdom 8-Nov-13 11-Nov-13
India 12-Nov-13 14-Nov-13
United Kingdom 15-Nov-13 18-Nov-13
India 19-Nov-13 21-Nov-13
United Kingdom 22-Nov-13 25-Nov-13
India 26-Nov-13 28-Nov-13
United Kingdom 29-Nov-13
请帮我一个SQL查询来实现这一目标。 提前谢谢。
答案 0 :(得分:6)
使用Tabibitosan:
SQL> create table mytable (date_worked,country)
2 as
3 select to_date('1-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
4 select to_date('4-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
5 select to_date('5-Nov-13','dd-Mon-yy'), 'India' from dual union all
6 select to_date('6-Nov-13','dd-Mon-yy'), 'India' from dual union all
7 select to_date('7-Nov-13','dd-Mon-yy'), 'India' from dual union all
8 select to_date('8-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
9 select to_date('11-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
10 select to_date('12-Nov-13','dd-Mon-yy'), 'India' from dual union all
11 select to_date('13-Nov-13','dd-Mon-yy'), 'India' from dual union all
12 select to_date('14-Nov-13','dd-Mon-yy'), 'India' from dual union all
13 select to_date('15-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
14 select to_date('18-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
15 select to_date('19-Nov-13','dd-Mon-yy'), 'India' from dual union all
16 select to_date('20-Nov-13','dd-Mon-yy'), 'India' from dual union all
17 select to_date('21-Nov-13','dd-Mon-yy'), 'India' from dual union all
18 select to_date('22-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
19 select to_date('25-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual union all
20 select to_date('26-Nov-13','dd-Mon-yy'), 'India' from dual union all
21 select to_date('27-Nov-13','dd-Mon-yy'), 'India' from dual union all
22 select to_date('28-Nov-13','dd-Mon-yy'), 'India' from dual union all
23 select to_date('29-Nov-13','dd-Mon-yy'), 'United Kingdom' from dual
24 /
Table created.
SQL> with tabibitosan as
2 ( select row_number() over (order by date_worked)
3 - row_number() over (partition by country order by date_worked) grp
4 , date_worked
5 , country
6 from mytable
7 )
8 select country
9 , min(date_worked) start_date
10 , max(date_worked) end_date
11 from tabibitosan
12 group by country
13 , grp
14 order by start_date
15 /
COUNTRY START_DATE END_DATE
-------------- ------------------- -------------------
United Kingdom 01-11-2013 00:00:00 04-11-2013 00:00:00
India 05-11-2013 00:00:00 07-11-2013 00:00:00
United Kingdom 08-11-2013 00:00:00 11-11-2013 00:00:00
India 12-11-2013 00:00:00 14-11-2013 00:00:00
United Kingdom 15-11-2013 00:00:00 18-11-2013 00:00:00
India 19-11-2013 00:00:00 21-11-2013 00:00:00
United Kingdom 22-11-2013 00:00:00 25-11-2013 00:00:00
India 26-11-2013 00:00:00 28-11-2013 00:00:00
United Kingdom 29-11-2013 00:00:00 29-11-2013 00:00:00
9 rows selected.
答案 1 :(得分:0)
比@ RobVanWijk的回答更复杂:
with v_data as (
select to_date('2013-11-01', 'YYYY-MM-DD') as date_worked, 'UK' as country from dual union all
select to_date('2013-11-04', 'YYYY-MM-DD') as date_worked, 'UK' as country from dual union all
select to_date('2013-11-05', 'YYYY-MM-DD') as date_worked, 'India' as country from dual union all
select to_date('2013-11-06', 'YYYY-MM-DD') as date_worked, 'India' as country from dual union all
select to_date('2013-11-07', 'YYYY-MM-DD') as date_worked, 'India' as country from dual union all
select to_date('2013-11-08', 'YYYY-MM-DD') as date_worked, 'UK' as country from dual union all
select to_date('2013-11-11', 'YYYY-MM-DD') as date_worked, 'UK' as country from dual union all
select to_date('2013-11-12', 'YYYY-MM-DD') as date_worked, 'India' as country from dual
)
select country, start_day, end_day from (
select
v3.*,
row_number() over (partition by start_day, end_day order by date_worked) as rn
from (
select
v2.*,
max(case when is_first_day = 1 then date_worked else null end) over (Partition by null order by date_worked) as start_day,
min(case when is_last_day = 1 then date_worked else null end) over (Partition by null order by date_worked desc) as end_day
from (
select
v1.*,
(case when country <> nvl(country_next_day, 'n/a') then 1 else 0 end) is_last_day,
(case when country <> nvl(country_prev_day, 'n/a') then 1 else 0 end) is_first_day
from (
select
date_worked,
country,
lead(country) over (order by date_worked) as country_next_day,
lag(country) over (order by date_worked) as country_prev_day
from v_data
) v1
) v2
order by date_worked
) v3
) v4 where rn=1
说明:
答案 2 :(得分:0)
尝试此查询:
select country,min(date_worked) as start_date,max(date_worked) as end_date
from (select country,date_worked,
Row_Number() over(order by date_worked)
-Row_Number() over(partition by country order by date_worked) as disTance
from YourTable)
group by disTance,country order by min(date_worked);