2015-07-28 6 views
1

я написал SQL заявление для расчета дней в течение каждого месяцасчета Oracle дней в месяц

(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. Я узнал, что он включает в себя 1 июля, что неправильно.

Знаете ли вы, как я могу рассказать свое маленькое заявление, он вычисляет только дни с месяца, в которые я хочу получить не включая дни из другого месяца?

ответ

3

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

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 месяцев текущую дату, а затем усекали ее до первого января, чтобы получить первый день нового года для простоты
  • Если вы хотите сделать это в течение месяца, возможно, стоит посмотреть на функцию 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 
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

'TO_CHAR (ДАТА, 'D')' зависит от 'настройки NLS_TERRITORY' - на некоторых территориях понедельник не первый день недели. – MT0

+0

@ MT0 спасибо, это правильно. –

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 | 
Смежные вопросы