Oracle每月计算天数

时间:2015-07-28 07:32:45

标签: sql oracle sysdate

我写了这个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月)之前一个月的天数。

六月有22天没有周末,但遗憾的是我的声明说有23天。我发现它包括7月1日,这是错误的。

你知道我怎么能告诉我的小说法它只计算从我想要的那个月开始的日子,不包括另一个月的日子吗?

3 个答案:

答案 0 :(得分:3)

做这种事总是看起来不漂亮......这是一种方式,它适用于整个当年。您可以通过向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

答案 1 :(得分:2)

首先,您的内部查询(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)会返回该月的日期加上下个月的一天。

其次,更简单的查询可以使用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;

答案 2 :(得分:1)

无需生成本月的所有日子,然后计算它们:

SQL Fiddle

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

<强> Results

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