sql >> Databáze >  >> RDS >> Oracle

Jak generovat řádky pro časové období podle klíče

v 10g/11g k tomu můžete použít vzorovou klauzuli.

SQL> with emps as (select rownum id, name, start_date,
  2                       end_date, trunc(end_date)-trunc(start_date) date_range
  3                  from table1)
  4  select name, the_date
  5    from emps
  6  model partition by(id as key)
  7        dimension by(0 as f)
  8        measures(name, start_date, cast(null as date) the_date, date_range)
  9        rules (the_date [for f from 0 to date_range[0] increment 1]  = start_date[0] + cv(f),
 10               name[any] = name[0]);

NAME        THE_DATE
----------- ----------
DAVID SMITH 01-01-2001
DAVID SMITH 01-02-2001
DAVID SMITH 01-03-2001
DAVID SMITH 01-04-2001
DAVID SMITH 01-05-2001
DAVID SMITH 01-06-2001
JOHN SMITH  02-07-2012
JOHN SMITH  02-08-2012
JOHN SMITH  02-09-2012

9 rows selected.

tj. váš základní dotaz:

select rownum id, name, start_date,
       end_date, trunc(end_date)-trunc(start_date) date_range
  from table1

pouze definuje data + rozsah (použil jsem rownum id, ale pokud máte PK, můžete ho použít místo toho.

oddíl rozdělí naše výpočty podle ID (unikátní řádek):

6  model partition by(id as key)

opatření:

8        measures(name, start_date, cast(null as date) the_date, date_range)

definuje atributy, které budeme vypisovat/vypočítávat. v tomto případě pracujeme s názvem a datem zahájení plus rozsahem řádků, které se mají vygenerovat. navíc jsem definoval sloupec the_date která bude obsahovat vypočítané datum (tj. chceme vypočítat počáteční_datum + n, kde n je od 0 do rozsahu.

pravidla definují, JAK zaplníme naše sloupce:

9        rules (the_date [for f from 0 to date_range[0] increment 1]  = start_date[0] + cv(f),
10               name[any] = name[0]);

takže s 

the_date [for f from 0 to date_range[0] increment 1]

říkáme, že vygenerujeme počet řádků, které datum_rozsah obsahuje +1 (tj. celkem 6 dat). hodnotu f lze odkazovat prostřednictvím cv (aktuální hodnota).

takže na řádku 1 pro Davida bychom měli the_date [0] = start_date+0 a následně na řádku 2 bychom měli the_date [1] = start_date+1 . celou cestu až do start_date+5 (tj. end_date )

p.s. pro připojení pomocí byste museli udělat něco takového:

select 
    A.EMPLOYEE_NAME,
    A.START_DATE+(b.r-1) AS INDIVIDUAL_DAY,
    TO_CHAR(A.START_DATE,'MM/DD/YYYY') START_DATE,
    TO_CHAR(A.END_DATE,'MM/DD/YYYY') END_DATE
FROM table1 A
     cross join (select rownum r
                   from (select max(end_date-start_date) d from table1)
                  connect by level-1 <= d) b
 where A.START_DATE+(b.r-1) <= A.END_DATE
 order by 1, 2;

tj. izolujte připojení k dílčímu dotazu a poté odfiltrujte řádky, kde individual_day> end_date.

ale tento postup NEDOPORUČUJI. jeho výkon bude horší ve srovnání s modelovým přístupem (zejména pokud se rozsahy zvětší).



  1. Neplatné přihlašovací údaje Oracle SQLPlus ORA-01017 při zadávání schématu

  2. PSQLException:Server požadoval ověření na základě hesla, ale nebylo poskytnuto žádné heslo

  3. Jak vybrat top N záznam z každé skupiny MySql

  4. Chart.js v2.6:Přidejte šipky k výstupním hodnotám koláčového grafu