2016-07-04 4 views

ответ

0

что-то вроде этого? (Он работает на текущий год) там отбрасывать данные от других лет

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 
+0

Это означает, что первая неделя (согласно стандарту ISO) начинается всегда 1 января, однако это не так. –

+0

Я редактирую sql, и теперь этот sql возвращает корректно для текущего года sysdate –

0

Если это не является проблема для добавления года в неделю вы ищете, вы также можете использовать это:

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 раза, если вы не используете переменную

0

Работа с 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;, однако это не было бы ошибок в безопасности, если кто-то использует неправильный год.

0

Вот простой и прямой расчет, использующий различные функции даты 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. 
+0

Это не работает для дат в будущем, только на прошлые недели. Также результат неправильный, когда вы выполняете запрос, например, 1 января 2016 года. –

+0

Я не согласен с первым наблюдением. Это должно работать одинаково хорошо в будущем, как в прошлом. Я полагаю, вы не слишком много думали; если вы считаете, что это так, пожалуйста, объясните, почему это не должно работать в течение нескольких недель в будущем. Во втором пункте я согласен в том смысле, что OP должен точно объяснить, какому календарному году ему нужен запрос, если он запущен 01 января-2016 года. – mathguy

Смежные вопросы