Thursday, November 17, 2005
Trabalhando com intervalos de DATAS
Durante nosso trabalho do dia-a-dia, muitas vezes nos deparamos com algumas situações onde temos que completar intervalos de datas. Veja abaixo três dúvidas comuns e as respectivas sugestões.
Gostaria de um exemplo de uma query que me retorna todos os dias do mês ?
Ex :
01/10/2005
02/10/2005
03/10/2005
04/10/2005
05/10/2005
ops$marcio@WIN10GR2> var mes number
ops$marcio@WIN10GR2>
ops$marcio@WIN10GR2> exec :mes := 10
PL/SQL procedure successfully completed.
MES
-------------
10
ops$marcio@WIN10GR2>
ops$marcio@WIN10GR2> with
2 x as
3 ( select trunc(to_date(:mes, 'mm')) + (level-1) dt
4 from dual
5 connect by 1=1 and level <= to_number(to_char(last_day(to_date(:mes, 'mm') ), 'dd'))
6 )
7 select * from x
8 /
DT
-------------------
01/10/2005 00:00:00
02/10/2005 00:00:00
03/10/2005 00:00:00
04/10/2005 00:00:00
05/10/2005 00:00:00
06/10/2005 00:00:00
07/10/2005 00:00:00
08/10/2005 00:00:00
09/10/2005 00:00:00
10/10/2005 00:00:00
11/10/2005 00:00:00
12/10/2005 00:00:00
13/10/2005 00:00:00
14/10/2005 00:00:00
15/10/2005 00:00:00
16/10/2005 00:00:00
17/10/2005 00:00:00
18/10/2005 00:00:00
19/10/2005 00:00:00
20/10/2005 00:00:00
21/10/2005 00:00:00
22/10/2005 00:00:00
23/10/2005 00:00:00
24/10/2005 00:00:00
25/10/2005 00:00:00
26/10/2005 00:00:00
27/10/2005 00:00:00
28/10/2005 00:00:00
29/10/2005 00:00:00
30/10/2005 00:00:00
31/10/2005 00:00:00
Alguém saberia me dizer como faço para -- através de SQL, sem ter que usar
PL -- retornar os nomes dos meses com o ano entre duas datas que serão
informado pelo usuário?
Exemplo: 01/10/2004 à 28/02/2005
Retorno: OUT-2004, NOV-2004, DEZ-2004, JAN-2005 e FEV-2005.
Para 9i um exemplo seria:
SQL> var dtini varchar2(20)
SQL> var dtfim varchar2(20)
SQL>
SQL> exec :dtini := '01/10/2004'
PL/SQL procedure successfully completed.
DTINI
--------------------------------
01/10/2004
SQL> exec :dtfim := '28/02/2005'
PL/SQL procedure successfully completed.
DTFIM
--------------------------------
28/02/2005
SQL>
SQL> with
2 mes
3 as ( select add_months(
4 trunc(to_date(:dtini, 'dd/mm/yyyy')),
5 level-1) dt
6 from dual
7 connect by 1=1
8 and level <= round(months_between(
9 to_date(:dtfim, 'dd/mm/yyyy'),
10 to_date(:dtini, 'dd/mm/yyyy')))
11 )
12 select to_char(dt, 'MON-yyyy',
13 'nls_date_language=portuguese') mes_ano
14 from mes
15 /
MES_ANO
--------
OUT-2004
NOV-2004
DEZ-2004
JAN-2005
FEV-2005
5 rows selected.
estou com um certo problema aqui,
preciso fazer uma sql que me retorne um
registro para cada dia util (tirando apenas
sabado e domingo, feriados pode retornar)
de um certo periodo, mas eu não tenho uma
tabela com os dias cadastrados...
o periodo pode ser variavel, por exemplo, o usuario
pode informar de 10/10/2005 a 20/10/2005 ou de
01/01/2005 a 31/12/2005 ou quaquer outra coisa
quer der na idéia dele.
eu tava quase criando a tabela e iria cadastrar
os dias uteis de uns cinco anos mais ou menos,
mas pensei em dar uma verificada melhor se
não teria uma maneira mais adequada pra
resolver isso...
ops$marcio@WIN10GR2> variable start_date varchar2(20)
ops$marcio@WIN10GR2> variable end_date varchar2(20)
ops$marcio@WIN10GR2> exec :start_date := '10/10/2005'
PL/SQL procedure successfully completed.
START_DATE
--------------------------------
10/10/2005
ops$marcio@WIN10GR2> exec :end_date := '20/10/2005'
PL/SQL procedure successfully completed.
END_DATE
--------------------------------
20/10/2005
ops$marcio@WIN10GR2>
ops$marcio@WIN10GR2> with dates
2 as
3 (select to_date(:start_date,'dd/mm/yyyy')+level-1 dt
4 from dual
5 connect by level <= to_date(:end_date,'dd/mm/yyyy')-to_date(:start_date,'dd/mm/yyyy')+1 )
6
7 select dt, to_char(dt,'Day') Week
8 from dates
9 where to_char(dt, 'd') not in (7,1)
10 /
DT WEEK
------------------- ---------
10/10/2005 00:00:00 Monday
11/10/2005 00:00:00 Tuesday
12/10/2005 00:00:00 Wednesday
13/10/2005 00:00:00 Thursday
14/10/2005 00:00:00 Friday
17/10/2005 00:00:00 Monday
18/10/2005 00:00:00 Tuesday
19/10/2005 00:00:00 Wednesday
20/10/2005 00:00:00 Thursday
9 rows selected.
Labels: how to