1

例えば:

@dtBegin = '2012-06-29' 

@input = 20

出力を。にしたい'2012-07-27'

4

5 に答える 5

1

私は自分のプロジェクトで同じ問題に取り組む必要がありました。Gordon Lionoffのソリューションは私を正しい軌道に乗せましたが、常に正しい結果をもたらすとは限りませんでした。週末から始まる日付も考慮に入れる必要があります。つまり、土曜日または日曜日に1営業日を追加すると、月曜日になります。これは、営業日の計算を処理するための最も一般的なアプローチです。

GordonLinoffの関数とPatrickMcDonaldの優れたC#に相当するものに基づいて独自のソリューションを作成しました

注:私のソリューションは、DATEFIRSTがデフォルト値の7に設定されている場合にのみ機能します。別のDATEFIRST値を使用する場合は、、、およびビットを変更する必要が1あり7ます(1,7,8,9,10)

私のソリューションは2つの機能で構成されています。エッジケースを処理する「外部」関数と実際の計算を実行する「内部」関数。どちらの関数もテーブル値関数であるため、実際には実装クエリに展開され、クエリオプティマイザを介して供給されます。

CREATE FUNCTION [dbo].[UTL_DateAddWorkingDays]
(   
    @date datetime,
    @days int
)
RETURNS TABLE AS RETURN 
(
    SELECT 
        CASE 
            WHEN @days = 0 THEN @date
            WHEN DATEPART(dw, @date) = 1 THEN (SELECT Date FROM [dbo].[UTL_DateAddWorkingDays_Inner](DATEADD(d, 1, @date), @days - 1))
            WHEN DATEPART(dw, @date) = 7 THEN (SELECT Date FROM [dbo].[UTL_DateAddWorkingDays_Inner](DATEADD(d, 2, @date), @days - 1))
            ELSE (SELECT Date FROM [dbo].[UTL_DateAddWorkingDays_Inner](@date, @days))
        END AS Date
)

ご覧のとおり、「外部」関数は以下を処理します。

  • 日を追加しない場合は、元の日付を返します。これにより、土曜日と日曜日の日付はそのまま保持されます。
  • 日曜日に日を追加するときは、月曜日から数え始めます。これには1日かかります。
  • 土曜日に日を追加する場合は、月曜日からカウントを開始します。これには1日かかります。
  • それ以外の場合は、通常の計算を行ってください

_

CREATE FUNCTION [dbo].[UTL_DateAddWorkingDays_Inner]
(   
    @date datetime,
    @days int
)
RETURNS TABLE AS RETURN 
(
    SELECT 
        DATEADD(d
        , (@days / 5) * 7 
          + (@days % 5) 
          + (CASE WHEN ((@days%5) + DATEPART(dw, @date)) IN (1,7,8,9,10) THEN 2 ELSE 0 END)
        , @date) AS Date
)

「内部」関数はGordonLinoffのソリューションに似ていますが、週末の境界を越える日付を考慮しますが、1週間の境界を越えることはありません。

最後に、関数をテストするためのテストスクリプトを作成しました。期待値は、Patrick McDonaldの優れたC#相当を使用して生成され、この人気のある計算機でこのデータをランダムに相互参照しました。

于 2012-09-20T15:23:26.013 に答える
0

これは私が試したことです:

CREATE function [dbo].[DateAddWorkDay]
(@days int,@FromDate Date)
returns Date
as
begin
declare @result date
set @result = (
select b
from
(
    SELECT
    b,
       (DATEDIFF(dd, a, b))
      -(DATEDIFF(wk, a, b) * 2)
      -(CASE WHEN DATENAME(dw, a) = 'Sunday' THEN 1 ELSE 0 END)
      -(CASE WHEN DATENAME(dw, b) = 'Saturday' THEN 1 ELSE 0 END)
      -COUNT(o.Holiday_Date) 
      as workday
    from
    (
    select 
    @FromDate as a,
    dateadd(DAY,num +@days,@FromDate) as b
    from (select row_number() over (order by (select NULL)) as num
          from Information_Schema.columns
         ) t
    where num <= 100 
    ) dt
    left join Holiday o on o.Holiday_Date between a and b and DATENAME(dw, o.Holiday_Date) not in('Saturday','Sunday') 
    where DATENAME(dw, b) not in('Saturday','Sunday')
          and b not in (select Holiday_Date from OP_Holiday where Holiday_Date between a and b) 

    group by a,b
) du
where workday =@days 

)
return @result 
end

休日の参考Holidayとなる表はどこにありますか。holiday_date

于 2014-06-28T02:51:01.123 に答える
0

これは、カレンダー テーブルやユーザー定義関数に頼らずに実行できます。

dateadd(d,
        (@input / 5) * 7 + -- get complete weeks out of the way
        mod(@input, 5) + -- extra days
        (case when ((@input%5) + datepart(dw, @dtbegin)%7) in (7, 1, 8) or
                   ((@input%5) + datepart(dw, @dtbegin)%7) < (@input%5)
              then 2
              else 0
         end),
        @dtbegin
       )

これがきれいだと言っているのではありません。ただし、結合やループよりも算術の方が望ましい場合があります。

于 2012-07-11T15:28:29.643 に答える