12

Oracle select で 2 つの日付間の営業日を計算しようとしています。私の計算では、指定された日付に対してほとんどの結果が正しくなるようになりました (Excel の NETWORKDAYS と比較します) が、2 日から -2 日まで変化する場合があり、その理由はわかりません...

これが私のコードです:

SELECT
((to_char(CompleteDate,'J') - to_char(InstallDate,'J'))+1) - (((to_char(CompleteDate,'WW')+ (52 * ((to_char(CompleteDate,'YYYY') - to_char(InstallDate,'YYYY'))))) - to_char(InstallDate,'WW'))*2) as BusinessDays
FROM TABLE

ありがとう!

4

12 に答える 12

31

最後に、解決策:

SELECT OrderNumber, InstallDate, CompleteDate,
  (TRUNC(CompleteDate) - TRUNC(InstallDate) ) +1 - 
  ((((TRUNC(CompleteDate,'D'))-(TRUNC(InstallDate,'D')))/7)*2) -
  (CASE WHEN TO_CHAR(InstallDate,'DY','nls_date_language=english')='SUN' THEN 1 ELSE 0 END) -
  (CASE WHEN TO_CHAR(CompleteDate,'DY','nls_date_language=english')='SAT' THEN 1 ELSE 0 END) as BusinessDays
FROM Orders
ORDER BY OrderNumber;

ご回答ありがとうございます。

于 2013-02-17T15:05:49.097 に答える
7

上記で説明したさまざまなアプローチをすべて考慮して、2 つの日付の間の各月の稼働日数を取得する簡単なクエリを作成しました。

WITH test_data AS ( SELECT TO_DATE('01-JAN-14') AS start_date, TO_DATE('31-DEC-14') AS end_date
FROM dual ), all_dates AS (
SELECT td.start_date, td.end_date, td.start_date + LEVEL-1 as week_day FROM test_data td CONNECT BY td.start_date + LEVEL-1 <= td.end_date) SELECT TO_CHAR(week_day, 'MON'), COUNT(*)
FROM all_dates WHERE to_char(week_day, 'dy', 'nls_date_language=AMERICAN') NOT IN ('sun' , 'sat') GROUP BY TO_CHAR(week_day, 'MON');

必要に応じてクエリを自由に変更してください。

于 2013-11-14T16:24:30.383 に答える
2

これを試して:

with holidays as 
(
select d from (
select minDate + level -1 d
 from (select min(submitDate) minDate, max (completeDate) maxDate
 from t)
 connect by level <= maxDate - mindate + 1) 
 where to_char(d, 'dy', 'nls_date_language=AMERICAN') not in ('sun' , 'sat')
)
select t.OrderNo, t.submitDate, t.completeDate, count(*) businessDays
from t join holidays h on h.d between t.submitDate and t.completeDate
group by t.OrderNo, t.submitDate, t.completeDate
order by orderno

これがsqlfiddleのデモです

于 2013-02-17T06:20:29.773 に答える
1

例を読みやすくし、バスの数を返すように変更しました。間の日。なぜ「J」-ジュリアン形式が必要なのかわかりません。必要なのは、開始/インストールと終了/完了の日付だけです。これを使用して、2つの日付の間の正しい日数を取得します。私の日付をあなたの日付に置き換え、必要に応じてNLSを追加してください...:

 SELECT Count(*) BusDaysBtwn
  FROM
  (
  SELECT TO_DATE('2013-02-18', 'YYYY-MM-DD') + LEVEL-1 InstallDate  -- MON or any other day 
       , TO_DATE('2013-02-25', 'YYYY-MM-DD') CompleteDate           -- MON or any other day
       , TO_CHAR(TO_DATE('2013-02-18', 'YYYY-MM-DD') + LEVEL-1, 'DY') InstallDay   -- day of week
    FROM dual 
  CONNECT BY LEVEL <= (TO_DATE('2013-02-25', 'YYYY-MM-DD') - TO_DATE('2013-02-18', 'YYYY-MM-DD')) -- end_date - start_date 
   )
   WHERE InstallDay NOT IN ('SAT', 'SUN')
  /

  SQL> 5
于 2013-02-15T16:17:28.323 に答える
1

マークされた最終的な解決策が常に正しいとは限らないことがわかりました。InstallDate がその月の 1 日 (土曜日の場合) で、CompleteDate がその月の 16 日 (日曜日の場合) であるとします。

その場合、実際の営業日は 10 ですが、マークされたクエリの結果は 12 と答えます。

(CASE WHEN TO_CHAR(InstallDate,'DY','nls_date_language=english')='SAT' AND TO_CHAR(CompleteDate,'DY','nls_date_language=english')='SUN' THEN 2 ELSE 0 END

それを処理するための行。

SELECT OrderNumber, InstallDate, CompleteDate,
(TRUNC(CompleteDate) - TRUNC(InstallDate) ) +1 - 
((((TRUNC(CompleteDate,'D'))-(TRUNC(InstallDate,'D')))/7)*2) -
(CASE WHEN TO_CHAR(InstallDate,'DY','nls_date_language=english')='SUN' THEN 1 ELSE 0 END) -
(CASE WHEN TO_CHAR(CompleteDate,'DY','nls_date_language=english')='SAT' THEN 1 ELSE 0 END) -
(CASE WHEN TO_CHAR(InstallDate,'DY','nls_date_language=english')='SAT' AND TO_CHAR(CompleteDate,'DY','nls_date_language=english')='SUN' THEN 2 ELSE 0 END)as BusinessDays
FROM Orders
ORDER BY OrderNumber;
于 2015-04-21T17:10:24.783 に答える
0

日曜日と土曜日を削除するには、これを使用できます

SELECT Base_DateDiff
     - (floor((Base_DateDiff + 0 + Start_WeekDay) / 7))
     - (floor((Base_DateDiff + 1 + Start_WeekDay) / 7))
FROM   (SELECT 1 + TRUNC(InstallDate) - TRUNC(InstallDate, 'IW') Start_WeekDay
             , CompleteDate - InstallDate + 1 Base_DateDiff
        FROM TABLE) a

Base_DateDiff2 つの日付の間の日数
(floor((Base_DateDiff + 0 + Start_WeekDay) / 7))を数える 日曜日
(floor((Base_DateDiff + 1 + Start_WeekDay) / 7))の数を数える 土曜日の数を数える

1 + TRUNC(InstallDate) - TRUNC(InstallDate, 'IW')月曜日の 1 から日曜日の 7 を取得します

于 2017-02-22T17:13:51.917 に答える
-1

どうぞ...

  1. まず、週末を除いて休日テーブルに何日入ったかを確認します。
  2. 2 つの日付の間の営業日 (月曜日から金曜日) を取得し、その後、休日の日を差し引きます。

    create or replace
    FUNCTION calculate_business_days (p_start_date IN DATE, p_end_date IN DATE)
            RETURN NUMBER IS
            v_holidays     NUMBER;
            v_start_date   DATE   := TRUNC (p_start_date);
            v_end_date     DATE   := TRUNC (p_end_date);
            BEGIN
            IF v_end_date >= v_start_date
            THEN
                    SELECT COUNT (*)
                    INTO v_holidays
                    FROM holidays
                    WHERE day BETWEEN v_start_date AND v_end_date
                    AND day NOT IN (
                            SELECT hol.day 
                            FROM holidays hol 
                            WHERE MOD(TO_CHAR(hol.day, 'J'), 7) + 1 IN (6, 7)
                    );
    
            RETURN   GREATEST (NEXT_DAY (v_start_date, 'MON') - v_start_date - 2, 0)
                 +   (  (  NEXT_DAY (v_end_date, 'MON')
                         - NEXT_DAY (v_start_date, 'MON')
                        )
                      / 7
                     )
                   * 5
                 - GREATEST (NEXT_DAY (v_end_date, 'MON') - v_end_date - 3, 0)
                 - v_holidays;
            ELSE
                    RETURN NULL;
            END IF;
    END calculate_business_days;
    

その後、次のようにテストできます。

    select 
            calculate_business_days('21-AUG-2013','28-AUG-2013') as business_days 
    from dual;
于 2013-08-21T14:55:03.963 に答える
-1

connect by と dual を使用する別の簡単な方法があります...

with t as (select to_date('30-sep-2013') end_date, trunc(sysdate) start_date from dual)select count(1) from dual, t where to_char(t.start_date  + level, 'D') not in (1,7) connect by t.start_date + level <= t.end_date;

connect by を使用すると、start_date から end_date までのすべての日付を取得できます。次に、不要な日付を除外して、必要な日付のみをカウントできます。

于 2013-09-12T15:25:18.550 に答える
-1

これは営業日を返します。

(CompleteDate-InstallDate)-2*FLOOR((CompleteDate-InstallDate)/7)-
  DECODE(SIGN(TO_CHAR(CompleteDate,'D')-
    TO_CHAR(InstallDate,'D')),-1,2,0)+DECODE(TO_CHAR(CompleteDate,'D'),7,1,0)-
    DECODE(TO_CHAR(InstallDate,'D'),7,1,0) as BusinessDays,
于 2018-03-05T17:26:49.593 に答える