2015-01-28 2 views
1

У меня есть приложение ApEx для отслеживания рабочего времени. У меня есть мнение, что выглядит следующим образом:С учетом даты выберите все номера недель в этом месяце

CREATE OR REPLACE VIEW HOURSDAYS 
AS SELECT 
(MAX("TO_X") - MIN("FROM_X"))*24 - 
(max(case when PROJECT_ID = 999 then to_x else to_date('01012000','DDMMYYYY') end) - 
    max(case when PROJECT_ID = 999 then from_x else to_date('01012000','DDMMYYYY') end))*24 AS TIME_SPENT, 
DAY, 
PERSON_ID 
FROM ATTENDANCE_HOURS 
GROUP BY PERSON_ID, DAY 
ORDER BY DAY DESC 

мне нужна сумма часов в неделю. Так что у меня есть это:

SELECT TO_CHAR(DAY,'IW'), MIN(DAY), MAX(DAY), SUM(TIME_SPENT) 
FROM HOURSDAYS 
WHERE PERSON_ID = (SELECT ID FROM ATTENDANCE_PEOPLE WHERE MAIL_SSO = V('APP_USER') AND ROLE = 0) AND 
EXTRACT (YEAR FROM DAY) = EXTRACT (YEAR FROM TO_DATE(:P100_DATE_PICKER,'DD-MON-RR')) 
GROUP BY TO_CHAR(DAY,'IW') 
ORDER BY TO_CHAR(DAY,'IW') ASC 

А теперь начинается самое интересное: у меня есть страница пункта P100_DATE_PICKER и мне нужно, чтобы отобразить только те недели, которые имеют> 0 дней, которые принадлежат к месяцу, к которому принадлежит этот день Я выбранный с помощью выбора даты. Например, для 1.1.2015 я хочу показать только недели 1, 2, 3, 4, 5. 243.2015: 9, 10, 11, 12, 13, 14.

Если кто-то заинтересован в том, зачем мне это делать, то для проверки - количество рабочих часов в неделю не может превышать 20/32, зависит от какой у вас контракт.

+0

Я не уверен, что вы имеете в виду под этим: '24.3.2015: 9, 10, 11, 12, 13, 14. «В марте пять воскресений и пять понедельников, так почему бы вы показать шесть недель? –

+0

@DavidFaber Неделя 9 с 2015-02-23 по 2015-03-01, так частично в марте. 14-я неделя с 2015-03-30 по 2015-04-05, так и частично в марте. Требование (как я понимаю) состоит в том, чтобы показать все недели частично или полностью в течение желаемого месяца и показать все данные за эти недели. Таким образом, в марте данные показывают от 2015-02-23 до 2015-04-05, сгруппированных этими 6 неделями. –

ответ

1

Вы можете сделать так:

where day >= trunc(trunc(TO_DATE(:P100_DATE_PICKER,'DD-MON-RR'), 'MM'),'IW') 
    and day < trunc(last_day(TO_DATE(:P100_DATE_PICKER,'DD-MON-RR')),'IW') + 7 

Первая строка начинается с trunc к MM, который дает в первый день месяца даты. Затем trunc снова до IW дает вам дату понедельника в неделю, которая содержит первый день месяца.

Вторая линия использует last_day, чтобы получить последний день месяца вашей даты. Затем trunc до IW получает понедельник , что неделю, и добавление 7 дней получает понедельник после. Затем, используя <, а не <=, вы получите желаемый результат.

Также предлагаю вам не группировать и заказывать TO_CHAR(DAY,'IW'), а вместо этого используйте TRUNC(DAY,'IW') для вашей группировки и заказа. В противном случае вы можете столкнуться с проблемами в течение нового года, потому что ваш код, например, показывающий недели за декабрь 2014 года, должен будет отображать 49-52 года 2014 года, а также неделю 1 года 2015 года. Если вы используете TO_CHAR, то на этой неделе 1 будет неправильно отсортированы до недель 49-52.

Аналогичным образом не используйте EXTRACT(YEAR FROM ...) или даже TO_CHAR(...,'YYYY'), когда вы работаете с неделями ISO. Поскольку дата «2014-12-31» относится к ИСО неделя 1 год 2015, существует специальная строка формата даты 'IYYY', которая дает правильный год для недели ИСО. Попробуйте и посмотрите разницу между 'YYYY' и 'IYYY'.

0

Лучший способ достижения последней части должен иметь календарную таблицу, которая имеет следующие столбцы

Дата, день, например, пн, месяц, квартал, год, WeekNo

Тогда для заданной даты вы можно просто выбрать все недели, которые относятся к месяцу.

Это позволяет определить weekNo так, чтобы оно соответствовало обстоятельствам компании. Например, иногда вы можете получить 53 неделя года, особенно если они работают периоды учета 4-4-5

+0

Это может быть полезно, да. Для конкретного вопроса это повлечет за собой * сначала * выбор недель, которые относятся к месяцу, и * затем * выбор всех дат, относящихся к этим неделям (так как некоторые из этих дат будут принадлежать либо предыдущему, либо следующему месяцу, и они также должны быть включены, чтобы получить все рабочие часы отображаемых недель.) –

+0

Итак, вы добавляете столбец кода месяца, который содержит yyyymm. Поэтому, когда вы выбираете месяц, он возвращает код yyyymm, а затем просматривайте недели, которые относятся к месяцу – Ewan

0
with days as (
    select 
     to_number(to_char(trunc(to_date('2015-03-24', 'yyyy-MM-dd'), 'month'), 'WW')) w1, 
     to_number(to_char(last_day(to_date('2015-03-24', 'yyyy-MM-dd')), 'WW')) w2 
    from dual) 
select w1+level-1 week from days 
    connect by level <= w2-w1+1 

days Subquery дает минимальную и максимальную недельную, запрос с connect by возвратов чисел между этими значениями.Пожалуйста, замените примерную дату: P100_DATE_PICKER.

1

Это не ответит на все ваши вопросы. Это быстрый пример расчета недели с определенной даты в соответствии с сюжетной линией вашего вопроса. Pls скопируйте/вставьте, чтобы увидеть результаты. Кроме того, вот ссылка, чтобы проверить неделю номера:

http://www.epochconverter.com/date-and-time/weeknumbers-by-year.php

SELECT given_date 
, end_date 
, TRUNC(calc_start_date, 'iw')     wk_starts 
, TRUNC(calc_start_date, 'iw') + 7 - 1/86400 wk_ends 
, TO_CHAR(calc_start_date, 'iw')    wk_number 
, calc_start_date 
FROM 
(
SELECT trunc(sysdate, 'mm')      given_date 
, trunc(sysdate, 'mm')-7 + LEVEL*7 AS  calc_start_date 
, Last_Day(trunc(SYSDATE, 'mm'))   end_date 
FROM dual 
CONNECT BY LEVEL <= ROUND((trunc(last_day(sysdate)) - trunc(sysdate, 'mm')+7)/7) -- number of weeks -- 
) 
/
GIVEN DATE END DATE WK_STARTS  WK_ENDS     WK NUMBER 
------------------------------------------------------------------------- 
1/1/2015 1/31/2015 12/29/2014 1/4/2015 11:59:59 PM 01 
1/1/2015 1/31/2015 1/5/2015  1/11/2015 11:59:59 PM 02 
1/1/2015 1/31/2015 1/12/2015  1/18/2015 11:59:59 PM 03 
1/1/2015 1/31/2015 1/19/2015  1/25/2015 11:59:59 PM 04 
1/1/2015 1/31/2015 1/26/2015  2/1/2015 11:59:59 PM 05 
Смежные вопросы