прямой перевод того, что у вас есть, кажется:
trunc(sysdate) - round((((trunc(sysdate) - date '1998-11-23')/14) - trunc((trunc(sysdate) - date '1998-11-23')/14)) * 14,0)
Но вы можете упростить, что:
trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
Два звонка trunc(sysdate)
дают текущую дату со временем, усеченным до полуночи, поэтому в настоящее время 2016-02-12. Если вычесть фиксированную дату начала (? Предположительно самый первый период в вашей системе), вы получите номер, from how Oracle does datetime arithmetic:
select trunc(sysdate) - date '1998-11-23' from dual;
TRUNC(SYSDATE)-DATE'1998-11-23'
---------------------------------------
6290
Поскольку оба дат были в полночи, что это целое число - целое число дней между сегодня и фиксированную дату. Если вы разделите это на 14, вы получите 449.285, что составляет 449 целых двухнедельных периодов и 0,285 текущего. Исходный расчет принимает это и удаляет усеченную версию 449, чтобы просто уйти с .285, а затем умножить на 14, чтобы вернуть эту оставшуюся часть в виде целого числа, которое равно 4.
Но это именно то, что дает the mod()
function - остаток n2 делится на n1 ". Другими словами, mod(6290, 14)
- это остаток от 6290, деленный на 14, что также равно 4. Он получает тот же результат от одного выражения вместо двух.
Итак, вы просто вычтите рассчитанное значение 4 с текущего дня, которое сегодня скажет вам об этом до 2016-02-08.
Видя, как это меняет для выбора сгенерированных дат:
with t (dt) as (
select trunc(sysdate) - level from dual connect by level < 21
)
select dt,
dt - round((((dt - date '1998-11-23')/14) - trunc((dt - date '1998-11-23')/14)) * 14) long_version,
dt - mod(dt - date '1998-11-23', 14) period_start,
dt - mod(dt - date '1998-11-23', 14) + 14 period_end
from t
order by dt;
DT LONG_VERSION PERIOD_START PERIOD_END
---------- ------------ ------------ ----------
2016-01-23 2016-01-11 2016-01-11 2016-01-25
2016-01-24 2016-01-11 2016-01-11 2016-01-25
2016-01-25 2016-01-25 2016-01-25 2016-02-08
2016-01-26 2016-01-25 2016-01-25 2016-02-08
...
2016-02-06 2016-01-25 2016-01-25 2016-02-08
2016-02-07 2016-01-25 2016-01-25 2016-02-08
2016-02-08 2016-02-08 2016-02-08 2016-02-22
2016-02-09 2016-02-08 2016-02-08 2016-02-22
2016-02-10 2016-02-08 2016-02-08 2016-02-22
2016-02-11 2016-02-08 2016-02-08 2016-02-22
Вы можете получить в конце периода путем добавления дней к результату, или вычислить его отдельно, используя дату начала 14 дней , Если вы ищете для записей в диапазоне вы могли бы сделать:
where some_date >= trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
and some_date < trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14) + 14
Если ни одна из дат, когда нет времени после полуночи (который может быть случаем для расписания) можно использовать between
и сделать конец периода 13 дней спустя, как вы предложили вы сейчас делаете в комментарии:
where some_date between trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14)
and trunc(sysdate) - mod(trunc(sysdate) - date '1998-11-23', 14) + 13
Я предпочитаю> = и < подход, хотя, как это не будет вам подножку, когда вы делаете что-то на данных, где раз действительно важно.
Используйте 'sysdate()' для 'Today',' to_date (1998-11-23, 'yyyy-mm-dd') 'for' Date (1998,11,23) '. – Spidey
@nimesh Нужно будет поместить тики вокруг ''1998-11-23'' – xQbert
@xQbert Вправо, пропустил это. – Spidey