Oracle 每月计算天数
Oracle count days per month
我写了这个SQL语句来计算每个月的天数
(select count(*) DAYs FROM
(
select trunc(ADD_MONTHS(sysdate,-1),'MM') + level -1 Dates from dual connect by
level <= ADD_MONTHS(trunc(sysdate,'MM'),1)-1 - trunc(sysdate,'MM')+1
) Where To_char(dates,'DY') NOT IN ('SA','SO'))
目前此语句忽略星期六和星期日,它从 sysdate 之前的月份(6 月)开始计算天数。
6 月有 22 天没有周末,但遗憾的是我的声明说它有 23 天。我发现它包括 7 月 1 日,这是错误的。
你知道我怎么知道我的小声明它只计算我想要获得的月份的天数,不包括另一个月份的天数吗?
做这种事情总是看起来不好看...这里有一种方法,它在整个当年都这样做。您可以通过向 where 子句添加附加语句来限制为一个月:
select to_char(trunc(sysdate, 'y') + level - 1, 'fmMON') as month, count(*)
from dual
where to_char(trunc(sysdate, 'y') + level - 1, 'fmDY', 'nls_date_language=english') not in ('SAT','SUN')
connect by level <= trunc(add_months(sysdate, 12), 'y') - trunc(sysdate, 'y')
group by to_char(trunc(sysdate, 'y') + level - 1, 'fmMON')
正如我所说,不漂亮。
注意几件事:
- 使用
fm
format model modifier 删除前导空格
- 明确使用
nls_date_language
以确保它在所有环境中都能正常工作
- 为了简单起见,我在当前日期上增加了 12 个月,然后将其截断到 1 月 1 日以获得新年的第一天
- 如果您想按月执行此操作,可能值得查看
LAST_DAY()
函数
上个月的相同语句(使用 LAST_DAY()
)将是:
select count(*)
from dual
where to_char(trunc(sysdate, 'y') + level - 1, 'fmDY', 'nls_date_language=english') not in ('SAT','SUN')
connect by level <= last_day(add_months(trunc(sysdate, 'mm'), -1)) - add_months(trunc(sysdate, 'mm'), -1) + 1
首先,您的内部查询 (select trunc(ADD_MONTHS(sysdate,-1),'MM') + level -1 Dates from dual connect by level <= ADD_MONTHS(trunc(sysdate,'MM'),1)-1 - trunc(sysdate,'MM')+1
) returns 这个月的天数加上下个月的额外一天。
其次,更简单的查询可以使用 LAST_DAY 函数来获取月份的最后一天。
最后,使用 'D'
日期格式获取星期几。
SELECT COUNT(*) FROM (
SELECT TO_CHAR(TRUNC(SYSDATE,'MM') + ROWNUM - 1, 'D') d
FROM dual CONNECT BY LEVEL <= TO_NUMBER(TO_CHAR(LAST_DAY(SYSDATE),'DD'))
) WHERE d BETWEEN 1 AND 5;
无需生成一个月中的所有日期然后计算它们:
Oracle 11g R2 模式设置:
CREATE FUNCTION WORK_DAYS_IN_MONTH(
dt DATE
) RETURN NUMBER DETERMINISTIC
AS
first_day DATE := TRUNC( dt, 'MM' );
remainder NUMBER := LAST_DAY( dt ) - ( first_day + INTERVAL '27' DAY );
BEGIN
RETURN 20 + CASE first_day - TRUNC( first_day, 'IW' )
WHEN 0 THEN remainder -- Monday
WHEN 1 THEN remainder -- Tuesday
WHEN 2 THEN remainder -- Wednesday
WHEN 3 THEN LEAST( remainder, 2 ) -- Thursday
WHEN 4 THEN LEAST( remainder, 1 ) -- Friday
WHEN 5 THEN GREATEST( remainder-2, 0 ) -- Saturday
ELSE GREATEST( remainder-1, 0 ) -- Sunday
END;
END;
//
查询 1:
SELECT ADD_MONTHS( DATE '2014-12-01', LEVEL ) AS "Month",
WORK_DAYS_IN_MONTH( ADD_MONTHS( DATE '2014-12-01', LEVEL ) ) AS "# Work Days"
FROM DUAL
CONNECT BY LEVEL <= 12
| Month | # Work Days |
|-----------------------------|-------------|
| January, 01 2015 00:00:00 | 22 |
| February, 01 2015 00:00:00 | 20 |
| March, 01 2015 00:00:00 | 22 |
| April, 01 2015 00:00:00 | 22 |
| May, 01 2015 00:00:00 | 21 |
| June, 01 2015 00:00:00 | 22 |
| July, 01 2015 00:00:00 | 23 |
| August, 01 2015 00:00:00 | 21 |
| September, 01 2015 00:00:00 | 22 |
| October, 01 2015 00:00:00 | 22 |
| November, 01 2015 00:00:00 | 21 |
| December, 01 2015 00:00:00 | 23 |
我写了这个SQL语句来计算每个月的天数
(select count(*) DAYs FROM
(
select trunc(ADD_MONTHS(sysdate,-1),'MM') + level -1 Dates from dual connect by
level <= ADD_MONTHS(trunc(sysdate,'MM'),1)-1 - trunc(sysdate,'MM')+1
) Where To_char(dates,'DY') NOT IN ('SA','SO'))
目前此语句忽略星期六和星期日,它从 sysdate 之前的月份(6 月)开始计算天数。
6 月有 22 天没有周末,但遗憾的是我的声明说它有 23 天。我发现它包括 7 月 1 日,这是错误的。
你知道我怎么知道我的小声明它只计算我想要获得的月份的天数,不包括另一个月份的天数吗?
做这种事情总是看起来不好看...这里有一种方法,它在整个当年都这样做。您可以通过向 where 子句添加附加语句来限制为一个月:
select to_char(trunc(sysdate, 'y') + level - 1, 'fmMON') as month, count(*)
from dual
where to_char(trunc(sysdate, 'y') + level - 1, 'fmDY', 'nls_date_language=english') not in ('SAT','SUN')
connect by level <= trunc(add_months(sysdate, 12), 'y') - trunc(sysdate, 'y')
group by to_char(trunc(sysdate, 'y') + level - 1, 'fmMON')
正如我所说,不漂亮。
注意几件事:
- 使用
fm
format model modifier 删除前导空格 - 明确使用
nls_date_language
以确保它在所有环境中都能正常工作 - 为了简单起见,我在当前日期上增加了 12 个月,然后将其截断到 1 月 1 日以获得新年的第一天
- 如果您想按月执行此操作,可能值得查看
LAST_DAY()
函数
上个月的相同语句(使用 LAST_DAY()
)将是:
select count(*)
from dual
where to_char(trunc(sysdate, 'y') + level - 1, 'fmDY', 'nls_date_language=english') not in ('SAT','SUN')
connect by level <= last_day(add_months(trunc(sysdate, 'mm'), -1)) - add_months(trunc(sysdate, 'mm'), -1) + 1
首先,您的内部查询 (select trunc(ADD_MONTHS(sysdate,-1),'MM') + level -1 Dates from dual connect by level <= ADD_MONTHS(trunc(sysdate,'MM'),1)-1 - trunc(sysdate,'MM')+1
) returns 这个月的天数加上下个月的额外一天。
其次,更简单的查询可以使用 LAST_DAY 函数来获取月份的最后一天。
最后,使用 'D'
日期格式获取星期几。
SELECT COUNT(*) FROM (
SELECT TO_CHAR(TRUNC(SYSDATE,'MM') + ROWNUM - 1, 'D') d
FROM dual CONNECT BY LEVEL <= TO_NUMBER(TO_CHAR(LAST_DAY(SYSDATE),'DD'))
) WHERE d BETWEEN 1 AND 5;
无需生成一个月中的所有日期然后计算它们:
Oracle 11g R2 模式设置:
CREATE FUNCTION WORK_DAYS_IN_MONTH(
dt DATE
) RETURN NUMBER DETERMINISTIC
AS
first_day DATE := TRUNC( dt, 'MM' );
remainder NUMBER := LAST_DAY( dt ) - ( first_day + INTERVAL '27' DAY );
BEGIN
RETURN 20 + CASE first_day - TRUNC( first_day, 'IW' )
WHEN 0 THEN remainder -- Monday
WHEN 1 THEN remainder -- Tuesday
WHEN 2 THEN remainder -- Wednesday
WHEN 3 THEN LEAST( remainder, 2 ) -- Thursday
WHEN 4 THEN LEAST( remainder, 1 ) -- Friday
WHEN 5 THEN GREATEST( remainder-2, 0 ) -- Saturday
ELSE GREATEST( remainder-1, 0 ) -- Sunday
END;
END;
//
查询 1:
SELECT ADD_MONTHS( DATE '2014-12-01', LEVEL ) AS "Month",
WORK_DAYS_IN_MONTH( ADD_MONTHS( DATE '2014-12-01', LEVEL ) ) AS "# Work Days"
FROM DUAL
CONNECT BY LEVEL <= 12
| Month | # Work Days |
|-----------------------------|-------------|
| January, 01 2015 00:00:00 | 22 |
| February, 01 2015 00:00:00 | 20 |
| March, 01 2015 00:00:00 | 22 |
| April, 01 2015 00:00:00 | 22 |
| May, 01 2015 00:00:00 | 21 |
| June, 01 2015 00:00:00 | 22 |
| July, 01 2015 00:00:00 | 23 |
| August, 01 2015 00:00:00 | 21 |
| September, 01 2015 00:00:00 | 22 |
| October, 01 2015 00:00:00 | 22 |
| November, 01 2015 00:00:00 | 21 |
| December, 01 2015 00:00:00 | 23 |