oracle pl- sql найти 3-ю среду указанной даты - PullRequest
0 голосов
/ 14 февраля 2020

В настоящее время у меня есть процесс, который принимает переменную даты EG: '01 -MAR-2026 ', затем он перебирает эту дату, проверяя, является ли день средой. Если это так, то увеличьте счетчик, иначе добавьте 1 день и проверьте снова. Это происходит, когда число среды равно = 3.

IF (to_char(v_Date,'dy') = 'wed') THEN
        v_NumWed := v_NumWed + 1;
END IF;

WHILE (v_NumWed != 3) LOOP
    v_Date := v_Date + interval '1' day;
    IF (to_char(v_Date, 'dy') = 'wed') THEN
        v_NumWed := v_NumWed + 1;
    END IF;
END LOOP;

Однако у меня есть ощущение, что есть более простой способ достичь этого, возможно, с помощью запроса или чего-то не используя al oop EG: использовать дату ввода и запрос, чтобы найти первую среду, а затем + 14 дней?

Любые предложения было бы здорово, заранее спасибо:)

РЕДАКТИРОВАТЬ: у меня есть что-то вроде этого, который, кажется, работает, также считает, если первый день - сама среда.

select next_day(trunc(v_date, 'MM') - 1, 'WED'), next_day(trunc(v_date, 'MM') - 1, 'WED') + 14 into v_first, v_third from dual;

решено: спасибо за помощь, получили несколько возможных решений в комментариях!

Ответы [ 3 ]

0 голосов
/ 14 февраля 2020

Чтобы получить третью среду от даты, включая эту дату, если ti сама среда, вы можете сделать:

select next_day(date '2026-03-01' + 13, 'Wednesday') from dual;

NEXT_DAY(D
----------
2026-03-18

Функция next_day немного неловкая, потому что она чувствительна к NLS и не имеет переопределения (как to_char()) - поэтому язык сеанса NLS и название / сокращение дня должны быть на одном языке. Если вы не можете управлять этим, то можете обойти его, получив название дня на текущем языке из известной фиксированной даты:

alter session set nls_date_language = 'French';

select to_char(date '2026-03-01', 'Day'),
  next_day(date '2026-03-01' + 13, to_char(date '1999-12-29', 'Day'))
from dual;

TO_CHAR( NEXT_DAY(D
-------- ----------
Dimanche 2026-03-18

Демо с некоторыми примерами дат:

with t (sample_date) as (
  select date '2026-02-15' + level
  from dual
  connect by level <= 31
)
select sample_date, next_day(sample_date + 13, 'Wednesday') as third_wed
from t
order by sample_date;

SAMPLE_DAT THIRD_WED 
---------- ----------
2026-02-16 2026-03-04
2026-02-17 2026-03-04
2026-02-18 2026-03-04
2026-02-19 2026-03-11
2026-02-20 2026-03-11
2026-02-21 2026-03-11
2026-02-22 2026-03-11
2026-02-23 2026-03-11
2026-02-24 2026-03-11
2026-02-25 2026-03-11
2026-02-26 2026-03-18
2026-02-27 2026-03-18
2026-02-28 2026-03-18
2026-03-01 2026-03-18
2026-03-02 2026-03-18
2026-03-03 2026-03-18
2026-03-04 2026-03-18
2026-03-05 2026-03-25
2026-03-06 2026-03-25
2026-03-07 2026-03-25
2026-03-08 2026-03-25
2026-03-09 2026-03-25
2026-03-10 2026-03-25
2026-03-11 2026-03-25
2026-03-12 2026-04-01
2026-03-13 2026-04-01
2026-03-14 2026-04-01
2026-03-15 2026-04-01
2026-03-16 2026-04-01
2026-03-17 2026-04-01
2026-03-18 2026-04-01
0 голосов
/ 14 февраля 2020

Я знаю, что вы уже решили проблему, просто хотели показать вам другой пример:

DECLARE
        dStartDate DATE := SYSDATE;
        dNextWednesDay DATE;
BEGIN
        FOR n IN 1..3 LOOP
                dNextWednesDay := NEXT_DAY(dStartDate, 'WEDNESDAY');
                DBMS_OUTPUT.PUT_LINE(dNextWednesDay);

                dStartDate := dNextWednesDay +1;
        END LOOP; 
END;
/

Вывод:

2020-02-19 15:33:58
2020-02-26 15:33:58
2020-03-04 15:33:58
0 голосов
/ 14 февраля 2020

Как насчет этого? Найдите первую среду (используя NEXT_DAY), которая следует за какой-то датой, и добавьте 14 дней (то есть 2 недели), чтобы найти третью среду.

SQL> alter session set nls_date_format = 'dd.mm.yyyy';

Session altered.

SQL> alter session set nls_date_language = 'english';

Session altered.

SQL> WITH test (col)
  2       AS (SELECT DATE '2020-01-27' FROM DUAL
  3           UNION ALL
  4           SELECT DATE '2020-02-06' FROM DUAL
  5           UNION ALL
  6           SELECT DATE '2020-02-12' FROM DUAL)
  7  SELECT col, NEXT_DAY (col, 'wed') + 14 next_3
  8    FROM test;

COL        NEXT_3
---------- ----------
27.01.2020 12.02.2020
06.02.2020 26.02.2020
12.02.2020 04.03.2020

SQL>

[EDIT]

Если оставленный вами комментарий означает, что - для любой даты - вы хотите найти 3-ю среду в этом месяце, затем обрезать дату до месяц (которая возвращает 1-й день в этом месяце) и найти 3-я среда, заботясь о том, является ли 1-й день месяца средой.

SQL> WITH test (col)
  2       AS (SELECT DATE '2020-01-27' FROM DUAL
  3           UNION ALL
  4           SELECT DATE '2020-02-06' FROM DUAL
  5           UNION ALL
  6           SELECT DATE '2020-03-18' FROM DUAL)
  7  SELECT col,
  8           NEXT_DAY (TRUNC (col, 'mm'), 'wed')
  9         + CASE
 10              WHEN TO_CHAR (TRUNC (col, 'mm'), 'dy') = 'wed' THEN 7
 11              ELSE 14
 12           END
 13            next_3
 14    FROM test;

COL        NEXT_3
---------- ----------
27.01.2020 15.01.2020
06.02.2020 19.02.2020
18.03.2020 18.03.2020

SQL>
...