Oracle
 sql >> Datenbank >  >> RDS >> Oracle

PL/SQL (Wie man den ersten und letzten Tag eines beliebigen Quartals eines Jahres berechnet)

Ich finde diese Frage sehr verwirrend. Wenn die eigentliche Frage ist, wie man das Viertel eines beliebigen DATE berechnet dann gibt es schon genug Beispiele, wie:

So berechnen Sie das Quartal eines beliebigen Datums

Einige Termine zum Testen:

create table lots_of_dates as
select trunc(sysdate - level * 7) as d
from dual
connect by level <= 52;

Viertel finden:

select d,
       to_char(d, 'YYYY-Q') as QUARTER,
       trunc(d, 'Q') as Q_FIRST_DAY,
       add_months(trunc(d, 'Q'), 3) - 1 as Q_LAST_DAY
from lots_of_dates
order by 1;

Ergebnisse:

D                  QUARTE Q_FIRST_DAY        Q_LAST_DAY
------------------ ------ ------------------ ------------------
02-SEP-12          2012-3 01-JUL-12          30-SEP-12
09-SEP-12          2012-3 01-JUL-12          30-SEP-12
16-SEP-12          2012-3 01-JUL-12          30-SEP-12
23-SEP-12          2012-3 01-JUL-12          30-SEP-12
30-SEP-12          2012-3 01-JUL-12          30-SEP-12
07-OCT-12          2012-4 01-OCT-12          31-DEC-12
14-OCT-12          2012-4 01-OCT-12          31-DEC-12
21-OCT-12          2012-4 01-OCT-12          31-DEC-12
28-OCT-12          2012-4 01-OCT-12          31-DEC-12
04-NOV-12          2012-4 01-OCT-12          31-DEC-12
11-NOV-12          2012-4 01-OCT-12          31-DEC-12
...

Eine PL/SQL-Prozedur, die den ersten und letzten Tag eines Quartals zurückgibt

Die Start- und Enddaten des Quartals sind für alle Jahre außer dem Jahresteil konstant. D.h. das zweite Quartal beginnt immer am 1. April und endet jedes Jahr am 30. Juni. Somit können Tag und Monat festgelegt werden und es muss nur der Jahresteil angepasst werden.

Eine Funktion kann nur einen Wert zurückgeben, daher wird die Subroutine stattdessen als Prozedur implementiert. Ich habe auch einen Funktionswrapper für die Prozedur bereitgestellt:

-- raises CASE_NOT_FOUND for non-existing quarters
create or replace procedure get_quarter_days(
  p_year in number,
  p_quarter in number,
  p_first_day out date,
  p_last_day out date
) deterministic as
begin
  case p_quarter
    when 1 then
      p_first_day := to_date(p_year || '-01-01', 'YYYY-MM-DD');
      p_last_day  := to_date(p_year || '-03-31', 'YYYY-MM-DD');
    when 2 then
      p_first_day := to_date(p_year || '-04-01', 'YYYY-MM-DD');
      p_last_day  := to_date(p_year || '-06-30', 'YYYY-MM-DD');
    when 3 then
      p_first_day := to_date(p_year || '-07-01', 'YYYY-MM-DD');
      p_last_day  := to_date(p_year || '-09-30', 'YYYY-MM-DD');
    when 4 then
      p_first_day := to_date(p_year || '-10-01', 'YYYY-MM-DD');
      p_last_day  := to_date(p_year || '-12-31', 'YYYY-MM-DD');
  end case;
end;
/
show errors

create or replace function get_quarter_first_day(
  p_year in number,
  p_quarter in number
) return date deterministic as
  v_first_day date;
  v_last_day date;
begin
  get_quarter_days(p_year, p_quarter, v_first_day, v_last_day);
  return v_first_day;
end;
/
show errors

create or replace function get_quarter_last_day(
  p_year in number,
  p_quarter in number
) return date deterministic as
  v_first_day date;
  v_last_day date;
begin
  get_quarter_days(p_year, p_quarter, v_first_day, v_last_day);
  return v_last_day;
end;
/
show errors

So verwenden Sie die obigen Unterroutinen:

declare
  v_first_day date;
  v_last_day date;
begin
  get_quarter_days(2011, 1, v_first_day, v_last_day);
  dbms_output.put_line(v_first_day || ' - ' || v_last_day);
  get_quarter_days(2012, 2, v_first_day, v_last_day);
  dbms_output.put_line(v_first_day || ' - ' || v_last_day);
  get_quarter_days(2013, 3, v_first_day, v_last_day);
  dbms_output.put_line(v_first_day || ' - ' || v_last_day);
  get_quarter_days(2014, 4, v_first_day, v_last_day);
  dbms_output.put_line(v_first_day || ' - ' || v_last_day);

  dbms_output.put_line(get_quarter_first_day(2015, 1) || ' - ' ||
                       get_quarter_last_day(2015, 1));
end;
/