2013-12-17 31 views
2

我有一張表,如下所示。Oracle:重複組中的最小最大值

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查詢來實現這一點。 在此先感謝。

回答

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. 
+0

清潔..高興,我也想出了相同辦法! –

+0

多數民衆贊成真棒。我認爲這是有效的。今天學習了一項新技術。非常感謝Rob –

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 

說明:

  • 每個工作日,讓繼任者,並使用滯後的前身()和lead()分析函數(v1)
  • 每個工作日,確定它是否是一個組的開始或結束其國家比較以前的和未來的國家(V2)
  • 每個組,計算開始和結束日(V3)
  • 爲每個工作日,計算其組內的排序(V4)
  • 回報僅限訂購1
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);