2

営業時間計算用のユーザー定義関数を作成しました。

これは私のUDFです。

CREATE FUNCTION  fn_GetBusinessHour (@date datetime, @addHours int)
RETURNS datetime
AS
BEGIN 
    DECLARE @CalcuatedDate datetime;
    DECLARE @addDayCount int, @addHourCount int, @addMinCount int;

    SET @addDayCount = @addHours / 8.5;
    SET @addHourCount = @addHours - (@addDayCount * 8.5);
    SET @addMinCount =  @addHours - (@addDayCount * 8.5) - @addHourCount;

    IF(@addDayCount != 0) 
        SET @CalcuatedDate = DATEADD(DD, @addDayCount, @date); 

    SET @CalcuatedDate = DATEADD(HH, @addHourCount, @CalcuatedDate);

    IF(@addMinCount != 0) 
        SET @CalcuatedDate = DATEADD(MM, @addMinCount, @CalcuatedDate); 

    RETURN @CalcuatedDate;
END

次のステートメントを使用してテストすると、

SELECT dbo.fn_GetBusinessHour(GETDATE(), 40)

適切な結果を示しています。

しかし、私はこのように私の関数を使用します、

SELECT TicketID
     , DateTimeLogged --Type: Datetime
     , Priority       --Type: int
     , [dbo].[fn_GetBusinessHour](DateTimeLogged, Priority)
  FROM TicketHeader

結果にはNULL値のみが表示されます。

TicketID    DateTimeLogged  Priority    (No column name)
1   2011-07-04 11:26:19.510     30  NULL
2   2011-07-04 13:58:45.683     30  NULL
3   2011-07-05 10:09:16.923     10  NULL
4   2011-07-05 13:13:30.237     30  NULL
5   2011-07-05 16:50:34.033     20  NULL

CONVERTを試したのは、値40を指定すると機能しましたが、null値も表示されるためです。

SELECT TicketID
         , DateTimeLogged --Type: Datetime
         , Priority       --Type: int
         , [dbo].[fn_GetBusinessHour](DateTimeLogged, CONVERT(int, Priority))
      FROM TicketHeader

これを修正してUDFを機能させるにはどうすればよいですか?なぜこのことが起こるのですか?Priorityと40の違いがわかりません。

前もって感謝します。

4

1 に答える 1

3

優先度が8.5を超える値の場合、これは私にとっては問題なく機能するようです。

DECLARE @t TABLE(TicketID INT, DateTImeLogged DATETIME, Priority INT);

INSERT @t SELECT 1,'20110704 11:26:19.510',30
UNION ALL SELECT 2,'20110704 13:58:45.683',30
UNION ALL SELECT 3,'20110705 10:09:16.923',10
UNION ALL SELECT 4,'20110705 13:13:30.237',30
UNION ALL SELECT 5,'20110705 16:50:34.033',20;

SELECT TicketID
     , DateTimeLogged --Type: Datetime
     , Priority       --Type: int
     , [dbo].[fn_GetBusinessHour](DateTimeLogged, Priority)
  FROM @t;

収量:

TicketID  DateTimeLogged           Priority  (No column name)
--------  -----------------------  --------  -----------------------
1         2011-07-04 11:26:19.510  30        2011-07-07 15:26:19.510
2         2011-07-04 13:58:45.683  30        2011-07-07 17:58:45.683
3         2011-07-05 10:09:16.923  10        2011-07-06 11:09:16.923
4         2011-07-05 13:13:30.237  30        2011-07-08 17:13:30.237
5         2011-07-05 16:50:34.033  20        2011-07-07 19:50:34.033

優先度が8.5未満の別の行を追加した場合、例:

INSERT @t SELECT 6,'20110705 13:13:30.237',5;

次に、この行が結果に追加されます。

TicketID  DateTimeLogged           Priority  (No column name)
--------  -----------------------  --------  -----------------------
6         2011-07-05 13:13:30.237  5         NULL

つまり、関数ロジックが@CalculatedDateを割り当てないままにすると、関数はNULLを出力します。これは、@ addDayCount=0の場合に発生します。

IF(@addDayCount != 0) 
    SET @CalcuatedDate = DATEADD(DD, @addDayCount, @date); 

@addDayCountはINTなので、これを試してください。

DECLARE @addDayCount INT;
SET @addDayCount = 5 / 8.5;
SELECT @addDayCount;

結果:

0

したがって、@ CalculatedDateには最初に値が割り当てられていないため、次のすべてのDATEADD操作はDATEADD(interval、number、NULL)を実行しますが、それでもNULLが生成されます。

したがって、関数内の変数に別のデータ型を使用する必要があるかもしれません...

于 2012-06-25T02:22:49.887 に答える