Пусть я вхожу WeekNo: 14 запрос должен возвращать С даты: 4 апреля 2016 года, так как неделю 14 начинается с 4 апреля по 10 апреляКак конвертировать номер недели, чтобы со дня недели в оракула
select to_date('14','iw') FROM dual;
Пусть я вхожу WeekNo: 14 запрос должен возвращать С даты: 4 апреля 2016 года, так как неделю 14 начинается с 4 апреля по 10 апреляКак конвертировать номер недели, чтобы со дня недели в оракула
select to_date('14','iw') FROM dual;
что-то вроде этого? (Он работает на текущий год) там отбрасывать данные от других лет
with dates as (select to_char(
to_date('1.01.'||extract(year from sysdate),'dd.mm.yyyy' ) + level -1
,'IW') we,
to_date('1.01.'||extract(year from sysdate),'dd.mm.yyyy' ) + level -1 da
from dual
connect by level <= 365 + 10)
select * from (
select case
when -- we = null if number of week in jan > 1,2,3,4....
((to_number(we) > 40)
and extract(year from sysdate) = extract(year from da)
and extract(month from da) = '01') or
-- we = null when current year < year of da
(extract(year from sysdate) != extract(year from da))
then
null
else we
end we,
da
from dates
)
where we = 14
and rownum = 1
Если это не является проблема для добавления года в неделю вы ищете, вы также можете использовать это:
SELECT (TRUNC (TO_DATE (SUBSTR ('201627', 1, 4) || '0131', 'YYYY'|| 'MMDD'), 'IYYY')
+ (7 * (TO_NUMBER (SUBSTR ('201627', 5)) - 1))) AS iw_Monday
FROM dual
В этом примере 201627
является YYYYIW
, который вы ищете. Он вернет дату ПОНЕДЕЛЬНИКА этой недели.
Найденный на Oracle forums, там есть несколько других решений. Я нашел, что это самый элегантный.
Преимущество состоит в том, что вы делаете все с SELECT
, и вам не нужна ни функция, ни PL/SQL, ни предложение WHERE
.
Недостатки: необходимо добавить в конец года и указать ваш поиск неделю 2 раза, если вы не используете переменную
Работа с ISO-недель не является тривиальной, например, 1 января 2016 неделя 53 см
select to_char(date '2016-01-01', 'iyyy-"W"iw') from dual;
Таким образом, обеспечивая только номер недели без (ISO-) год неоднозначно - хотя это очевидно, как по мере того как вы не вокруг даты новых лет.
Некоторое время назад я написал эту функцию, чтобы получить дату с ISO-Week.
FUNCTION ISOWeekDate(week INTEGER, YEAR INTEGER) RETURN DATE DETERMINISTIC IS
res DATE;
BEGIN
IF week > 53 OR week < 1 THEN
RAISE VALUE_ERROR;
END IF;
res := NEXT_DAY(TO_DATE(YEAR || '0104', 'YYYYMMDD') - 7, 'MONDAY') + (week - 1) * 7;
IF TO_CHAR(res, 'fmIYYY') = YEAR THEN
RETURN res;
ELSE
RAISE VALUE_ERROR;
END IF;
END ISOWeekDate;
Конечно, вы можете просто выбрать NEXT_DAY(TO_DATE(YEAR || '0104', 'YYYYMMDD') - 7, 'MONDAY') + (week - 1) * 7;
, однако это не было бы ошибок в безопасности, если кто-то использует неправильный год.
Вот простой и прямой расчет, использующий различные функции даты Oracle. Поскольку он сравнивается с тем, что Oracle уже считает неделей ISO и т. Д., Он не должен подвергаться никаким трудностям, которые другие решения правильно указывают на дополнительный код и обращаются к нему.
«Магическое число» 14
в формуле должно вместо этого быть переменной связывания, возможно :iw
или каким-либо другим механизмом ввода номера недели ISO в запрос.
select trunc(sysdate, 'iw') - 7 * (to_number(to_char(trunc(sysdate), 'iw')) - 14) as dt
from dual;
DT
----------
2016-04-04
1 row selected.
Это не работает для дат в будущем, только на прошлые недели. Также результат неправильный, когда вы выполняете запрос, например, 1 января 2016 года. –
Я не согласен с первым наблюдением. Это должно работать одинаково хорошо в будущем, как в прошлом. Я полагаю, вы не слишком много думали; если вы считаете, что это так, пожалуйста, объясните, почему это не должно работать в течение нескольких недель в будущем. Во втором пункте я согласен в том смысле, что OP должен точно объяснить, какому календарному году ему нужен запрос, если он запущен 01 января-2016 года. – mathguy
Это означает, что первая неделя (согласно стандарту ISO) начинается всегда 1 января, однако это не так. –
Я редактирую sql, и теперь этот sql возвращает корректно для текущего года sysdate –