Como posso extrair e exibir o intervalo de datas baseado no Trimestre no Oracle?
-
13-12-2019 - |
Pergunta
Estou construindo uma tabela de resumo como parte de um procedimento armazenado e tenho duas colunas.A primeira coluna precisa mostrar o início e a segunda coluna precisa mostrar o final de um intervalo de datas baseado em um parâmetro de entrada que é um número que designa o trimestre.Consegui extrair o seguinte do AskTom, mas tenho algumas dúvidas.
Open C1 FOR
SELECT ( SELECT TRUNC (SYSDATE, 'Q')-1+1 AS 'StartOf' FROM DUAL ),
SELECT ( SELECT TRUNC(ADD_MONTHS (SYSDATE, +3), 'Q')-2 AS 'EndOf' FROM DUAL )
FROM DUAL;
Questão 1.A matemática aqui será responsável pelos anos bissextos...Acho que não, mas não tenho certeza de como lidar com isso.
Questão 2.Como adiciono o parâmetro de entrada 'inQuarter' como o trimestre específico?Tentei colocá-lo no lugar do sysdate, mas primeiro preciso reformatá-lo para data, acho?
Agradecemos antecipadamente a todas as respostas.
Solução
Tom Kyte deu a você a resposta:http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:250288900346075009
Open C1 FOR
select add_months( dt, (inQuarter-1)*3 ),
last_day(add_months( dt, (inQuarter-1)*3+2 ) )
from (
select to_date( inYear || '0101', 'yyyymmdd' ) dt
from dual)
Outras dicas
Você pode converter um parâmetro numérico de ano e trimestre numérico em um DATE
SELECT add_months( trunc( to_date( to_char( <<numeric year>> ),
'YYYY' ),
'YYYY' ),
3 * <<numeric quarter>> ) first_of_quarter,
add_months( trunc( to_date( to_char( <<numeric year>> ),
'YYYY' ),
'YYYY' ),
4 * <<numeric quarter>> ) - 1 last_of_quarter,
FROM dual
O componente horário de ambas as datas será meia-noite do último dia do trimestre (ou seja,24 horas antes do início do próximo trimestre).Você pode querer que o último dia do trimestre seja 23:59:59 do último dia do trimestre se quiser que o intervalo inclua todas as datas possíveis no trimestre.
Eu sugiro:
Open C1 FOR
SELECT TRUNC (d_inQuarter, 'Q') AS "StartOf",
TRUNC(ADD_MONTHS (d_inQuarter, +3), 'Q') AS "EndOf"
FROM (SELECT add_months(to_date(to_char(i_yr)||'-01-01','YYYY-MM-DD'), (i_q-1)*3)
AS d_inQuarter FROM DUAL);
- com parâmetros inteiros i_yr e i_q representando o ano e o trimestre, respectivamente.
Observe que EndOf representará a meia-noite do primeiro dia do próximo trimestre, portanto, qualquer seleção deverá ser baseada nas condições < "EndOf"
, não <= "EndOf"
.(Isso deve garantir que todos os horários do último dia do trimestre sejam incluídos.)