我有一个用于跟踪工作时间的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周。 24.3.2015:9,10,11,12,13,14。
如果有人对我为什么这样做感兴趣,那就是验证 - 每周的工作时数不能超过20/32,具体取决于你的合约类型。
答案 0 :(得分: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年12月的周数时必须显示2014年的49到52年以及2015年的第1周。如果你使用TO_CHAR
那么在第49周至第52周之前,第1周将被错误地分类。
同样,在使用ISO周时,请勿使用EXTRACT(YEAR FROM ...)
甚至TO_CHAR(...,'YYYY')
。由于日期'2014-12-31'属于ISO第1周2015年,因此有一个特殊的日期格式字符串'IYYY'
,它为ISO周提供正确的年份。试一试,看看'YYYY'
和'IYYY'
之间的区别。
答案 1 :(得分:1)
这不会回答你的所有问题。这是根据您问题的主题行从给定日期开始的周计算的快速示例。请复制/粘贴以查看结果。此外,这里是检查周数的链接:
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
答案 2 :(得分:0)
实现最后一部分的最佳方法是拥有一个包含以下列的日历表
日期,日,例如星期一,月,季,年,星期
然后,对于给定日期,您只需选择属于该月份的所有周。
这允许您定义weekNo以使其适合公司环境。例如,偶尔您可能会获得53周的年度,特别是如果他们运行4-4-5个会计期间
答案 3 :(得分: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
给出最小和最长周,查询connect by
返回这些值之间的数字。请将示例日期替换为:P100_DATE_PICKER。