2009-06-02 11 views
5
site_id | start_date | end_date 
     1 | oct 1, 08 | oct 2, 08 
     1 | oct 2, 08 | oct 3, 08 
... 
     1 | oct 30, 08 | oct 31, 08 
     2 | oct 1, 08 | oct 2, 08 
     2 | oct 2, 08 | oct 3, 08 
... 
     2 | oct 30, 08 | oct 31, 08 

Mam tabelę, która zawiera 1 rekord na stronę na dzień miesiąca (na miesiąc w roku). Muszę być w stanie określić, czy strona na dany miesiąc ma co najmniej 15 sąsiadujących rekordów, i muszę znać datę rozpoczęcia i zakończenia tej serii sąsiednich dni. Mogę to zrobić w procedurze przechowywanej, ale miałem nadzieję, że można to osiągnąć w jednym zapytaniu. Mam do czynienia z dość dużym zbiorem danych, co najmniej 30 milionów rekordów miesięcznie.Jak skutecznie wyszukiwać ciągłe zestawy dat w zbiorze danych?

Przykład Wyniki:

site_id | contiguous_start_date | contiguous_end_date 
     1 | oct 5, 2008   | oct 20, 2008 
     2 | oct 10    | oct 30, 2008 
     3 | oct 1     | oct 31, 2008 

dzięki za pomoc!

+0

Kiedy "data_końcowa" nie jest równa "data_początkowa + 1 dzień"? Ponieważ zapytanie jest prostsze, jeśli nie ma potrzeby przeglądania obu kolumn. –

Odpowiedz

4

Oto przykład jak zrobić takie zapytanie:

SQL> create table t (site_id,start_date,end_date) 
    2 as 
    3 select 1, date '2008-10-01', date '2008-10-02' from dual union all 
    4 select 1, date '2008-10-02', date '2008-10-03' from dual union all 
    5 select 1, date '2008-10-03', date '2008-10-30' from dual union all 
    6 select 1, date '2008-10-30', date '2008-10-31' from dual union all 
    7 select 2, date '2008-10-01', date '2008-10-02' from dual union all 
    8 select 2, date '2008-10-02', date '2008-10-03' from dual union all 
    9 select 2, date '2008-10-03', date '2008-10-04' from dual union all 
10 select 2, date '2008-10-04', date '2008-10-05' from dual union all 
11 select 2, date '2008-10-05', date '2008-10-06' from dual union all 
12 select 2, date '2008-10-06', date '2008-10-07' from dual union all 
13 select 2, date '2008-10-07', date '2008-10-08' from dual union all 
14 select 2, date '2008-10-08', date '2008-10-09' from dual union all 
15 select 2, date '2008-10-09', date '2008-10-10' from dual union all 
16 select 2, date '2008-10-10', date '2008-10-11' from dual union all 
17 select 2, date '2008-10-11', date '2008-10-12' from dual union all 
18 select 2, date '2008-10-12', date '2008-10-13' from dual union all 
19 select 2, date '2008-10-13', date '2008-10-14' from dual union all 
20 select 2, date '2008-10-14', date '2008-10-15' from dual union all 
21 select 2, date '2008-10-15', date '2008-10-16' from dual union all 
22 select 2, date '2008-10-16', date '2008-10-17' from dual union all 
23 select 2, date '2008-10-17', date '2008-10-18' from dual union all 
24 select 2, date '2008-10-18', date '2008-10-19' from dual union all 
25 select 2, date '2008-10-19', date '2008-10-20' from dual union all 
26 select 3, date '2008-10-01', date '2008-10-02' from dual union all 
27 select 3, date '2008-10-02', date '2008-10-03' from dual union all 
28 select 3, date '2008-10-03', date '2008-10-04' from dual union all 
29 select 3, date '2008-10-04', date '2008-10-05' from dual union all 
30 select 3, date '2008-10-05', date '2008-10-06' from dual union all 
31 select 3, date '2008-10-06', date '2008-10-07' from dual union all 
32 select 3, date '2008-10-07', date '2008-10-08' from dual union all 
33 select 3, date '2008-10-08', date '2008-10-09' from dual union all 
34 select 3, date '2008-10-09', date '2008-10-10' from dual union all 
35 select 3, date '2008-10-30', date '2008-10-31' from dual 
36/

Tabel is aangemaakt. 

I wtedy zapytanie:

SQL> select site_id 
    2  , min(start_date) contiguous_start_date 
    3  , max(end_date) contiguous_end_date 
    4  , count(*) number_of_contiguous_records 
    5 from (select site_id 
    6    , start_date 
    7    , end_date 
    8    , max(rn) over (partition by site_id order by start_date) maxrn 
    9    from (select site_id 
10       , start_date 
11       , end_date 
12       , case lag(end_date) over (partition by site_id order by start_date) 
13        when start_date then null 
14        else rownum 
15       end rn 
16      from t 
17     ) 
18   ) 
19 group by site_id 
20  , maxrn 
21 order by site_id 
22  , contiguous_start_date 
23/

A wyniki:

SITE_ID CONTIGUOUS_START_DA CONTIGUOUS_END_DATE NUMBER_OF_CONTIGUOUS_RECORDS 
---------- ------------------- ------------------- ---------------------------- 
     1 01-10-2008 00:00:00 31-10-2008 00:00:00       4 
     2 01-10-2008 00:00:00 20-10-2008 00:00:00       19 
     3 01-10-2008 00:00:00 10-10-2008 00:00:00       9 
     3 30-10-2008 00:00:00 31-10-2008 00:00:00       1 

4 rijen zijn geselecteerd. 

Pozdrowienia, Rob .

+0

Sprytne podejście do rozwiązania problemu. Dzięki. –

+0

+1 Cool, lag (end_date) = data_początkowa. – Andomar

1

Jest to zdecydowanie bardzo możliwe. Rozwiązałem podobny problem w SQL Server kilka miesięcy temu. Nie wiem nic o składni Oracle, więc obawiam się, że nie mogę się przekonwertować, jeśli dla ciebie, ale jeśli jesteś solidny w Oracle, to wystarczy this, aby cię tam zabrać.

-1

struktury bazy danych nie nadaje się do logiki biznesowej masz:

  • end_date zawsze jest następny dzień po datą_początkową to dlaczego trzeba przechowywać go w db?
  • Widzę, że w podanym przykładzie danych nie ma spacji w zakresie dat dla pojedynczej witryny. Oznacza to, że nie trzeba przechowywać całego okresu dat tylko data rozpoczęcia i zakończenia.

30 milionów rekordów miesięcznie to naprawdę tabela dla zapytania, które musisz napisać. Wykonaj refaktoryzację konstrukcyjną tej tabeli to moja rada.

Powiązane problemy