Как я могу извлечь и отобразить диапазон дат на основе квартала в Oracle?

Я создаю сводную таблицу как часть хранимой процедуры, и у меня есть два столбца. В первом столбце должно отображаться начало, а во втором столбце — конец диапазона дат, основанного на входном параметре, представляющем собой число, обозначающее квартал. Мне удалось извлечь из AskTom следующее, но у меня есть несколько вопросов.

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; 

Вопрос 1. Будет ли математика здесь учитывать високосные годы... Я не думаю, что будет, но я не уверен, как с этим справиться.

Вопрос 2. Как добавить входной параметр inQuarter в качестве конкретного квартала? Я пытался поставить его вместо sysdate, но мне нужно сначала переформатировать его в дату, я думаю?

Заранее спасибо за любые ответы.


person dee    schedule 13.03.2012    source источник
comment
Почему у вас -1+1? - это просто отменяется. Где нужно учитывать високосные годы? Даты кварталов: 1 января, 1 апреля, 1 июля и 1 октября — это то, что вы должны использовать для конкретных кварталов.   -  person David Faber    schedule 13.03.2012
comment
@dee - Что представляет собой inQuarter? Вы говорите, что это число, обозначающее квартал, которое, по-видимому, означает для вас что-то очень конкретное, но мне непонятно, что это значит. Вы имеете в виду, что вы передаете число, подобное 1, которое должно интерпретироваться как первый квартал текущего года? Или что у вас есть число вроде 200403, которое должно интерпретироваться как 3-й квартал 2004 года? Или что-то другое?   -  person Justin Cave    schedule 13.03.2012
comment
Извиняюсь, что не разъяснил должным образом. inQuarter — это однозначное число от 1 до 4, обозначающее квартал. Это также напоминает мне, что существует также inYear, который равен YYYY, оба из которых должны указать мне первый и последний день квартала, который они указывают. Спасибо за быстрые ответы.   -  person dee    schedule 13.03.2012
comment
@Фабер. Я не уверен, как объяснить математику сам, но +1-1 дает мне 2012-01-01, в то время как просто -1 возвращает 2011-12-31, а +1 возвращает 2012-01-02. Я предполагаю, что числа здесь работают на уровне форматирования больше, чем на математическом уровне, поэтому мне любопытно, работают високосные годы или нет.   -  person dee    schedule 13.03.2012
comment
@dee, тебе не нужны +1-1 или -1+1 - просто избавься от обоих.   -  person David Faber    schedule 13.03.2012


Ответы (3)


Том Кайт дал вам ответ: http://asktom.oracle.com/pls/asktom/f?p=100:11:0%3a%3a%3a%3aP11_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)
person A.B.Cade    schedule 13.03.2012
comment
Спасибо, А.Б. эээ Том... эээ А.Б. ... Это сработало совершенно правильно. Я тоже начал с AskTom... не знаю, как я это пропустил. - person dee; 13.03.2012

Вы можете преобразовать числовой параметр года и числового квартала в 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

Временная составляющая обеих дат будет полуночью последнего дня квартала (т. е. за 24 часа до начала следующего квартала). Вы можете захотеть, чтобы последний день квартала был 23:59:59 в последний день квартала, если вы хотите, чтобы диапазон включал все возможные даты в квартале.

person Justin Cave    schedule 13.03.2012
comment
Все три ответа предоставили всю работу. Спасибо всем за уделенное время. - person dee; 13.03.2012

Я предлагаю:

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); 

- с целочисленными параметрами i_yr и i_q, представляющими год и квартал соответственно.

Обратите внимание, что EndOf будет представлять полночь первого дня следующего квартала, поэтому любой выбор должен основываться на условиях < "EndOf", а не <= "EndOf". (Это должно гарантировать, что все времена в последний день квартала включены.)

person Community    schedule 13.03.2012
comment
Спасибо, Марк, это определенно похоже на то, что я позабочусь о своем вопросе о високосном году. Любая идея, как я могу извлечь дату из двух заданных параметров? - person dee; 13.03.2012