1

我写了这个 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(六月)前一个月开始计算天数。

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

你知道我怎么能告诉我的小声明它只计算我想要得到的月份的天数,不包括另一个月份的天数?

4

3 回答 3

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格式模型修饰符删除前导空格
  • 明确使用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
于 2015-07-28T07:48:44.867 回答
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;
于 2015-07-28T07:52:57.957 回答
1

无需生成一个月中的所有日期然后计算它们:

SQL小提琴

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 |
于 2015-07-28T08:54:48.457 回答