2012-01-18 6 views
0

開始時間と終了時間が与えられたら、与えられた時間内の何分が処理されるかを知りたいと思います。与えられた時間に何分が使用されたかを計算します。

create function CalcMinsInHour(@start datetime, @end datetime, @hour int) 
returns int 
as 
begin 
    --Looking for best way to write this part 
end 

CalcMinsInHour('2012-01-18 8:15', '2012-01-18 10:30', 7) should return 0 
CalcMinsInHour('2012-01-18 8:15', '2012-01-18 10:30', 8) should return 45 
CalcMinsInHour('2012-01-18 8:15', '2012-01-18 10:30', 9) should return 60 
CalcMinsInHour('2012-01-18 8:15', '2012-01-18 10:30', 10) should return 30 
CalcMinsInHour('2012-01-18 8:15', '2012-01-18 10:30', 11) should return 0 

編集:@Startと@Endは、従業員のクロックイン/アウト時間を表します。だから、彼らは深夜過ぎに働いたときに2日間に及ぶことができますが、それ以上はできません。

+2

は、日付の範囲です同じ日にのみ保証されていますか? – RQDQ

+1

ベストセラー? 「方法」のように聞こえます。 :) – bzlm

+1

複数の日間をどのように処理したいですか? '2012-01-18 8:15'と' 2012-01-20-13:30'と入力すれば、何を得たいですか? – JNK

答えて

3

これはトリックを行う必要があります。

ALTER FUNCTION dbo.CalcMinsInHour(@start DATETIME, @end DATETIME, @hour INTEGER) 
RETURNS INTEGER 
AS 
BEGIN 
    DECLARE @StartOfHour DATETIME 
    DECLARE @EndOfHour DATETIME 
    SELECT @StartOfHour = DATEADD(hh, @hour, CAST(CAST(@start AS DATE) AS DATETIME)) 
    IF NOT (@StartOfHour BETWEEN @start and @end) 
     SET @StartOfHour = DATEADD(hh, @hour, CAST(CAST(@end AS DATE) AS DATETIME)) 

    SELECT @EndOfHour = DATEADD(hh, 1, @StartOfHour) 

RETURN 
(
SELECT 
    CASE WHEN @EndOfHour < @start OR @StartOfHour > @end THEN 0 ELSE 
     DATEDIFF(mi, 
      CASE WHEN @StartOfHour <= @start THEN @start ELSE @StartOfHour END, 
      CASE WHEN @EndOfHour > @end THEN @end ELSE @EndOfHour END) 
    END 
) 
END 
+0

+1 - 私はまだ完了していない私のbazillion 'CASE'ステートメントのソリューションよりもはるかにエレガントです:) – JNK

+0

これは、間隔が '2012-01-18 20:15' - '2012-01-19 2:30'で、時間が2の場合には機能しません。例えば、 – GolfWolf

+0

あなたは驚きます。あなたがダラスにいるなら、私はあなたの昼食を買うでしょう:) –

1

DateDiffを使用できますか?

select DATEDIFF(Minute, '2011-11-10 00:00:59.900', '2011-11-10 00:01:00.100')

+0

私はそれが複数のDateDiffのcase文でなければならないと思う。アイデアは、その日の1時間あたりの労働時間の合計を得ることです。 –

1

ここで数分の合計数を計算する関数は、(また、複数の日で動作します)です:

create function CalcMinsInHour(@start datetime, @end datetime, @hour int) 
    returns int 
as 
begin 

    declare @selecterHourIntervals table (HourStart datetime, HourEnd datetime) 
    declare @currentDate datetime 

    /* start in the @start date, but the hour we want to count */ 
    set @currentDate = dateadd(hour, @hour, convert(datetime, convert(date, @start))) 

    /* for every day between @[email protected] add out hour interval */ 
    while @currentDate <= @end 
    begin 
     insert into @selecterHourIntervals values (
         @currentDate, 
         dateadd(hour, 1, @currentDate)) 

     set @currentDate = dateadd(day, 1, @currentDate) 
    end 

    declare @totalMinutes int 

    /* for every hour interval in the table, select number of minutes 
     trimmed by the @start - @end interval and sum */ 
    select @totalMinutes = sum(DailyMinutes) 
    from 
     (select 
      datediff(minute, 
      case when HourStart > @start then HourStart else @start end, 
      case when HourEnd < @end then HourEnd else @end end) as DailyMinutes 
     from @selecterHourIntervals) TrimmedIntervals 
    where DailyMinutes > 0 

    return isnull(@totalMinutes, 0) 

end 
+0

+1の努力のために: –

+0

私はこの答えがAdaTheDevのものよりも "正しい"ものであることを認識していますが、実際にループや一時テーブルなどを使わずに解決策を求めていました。努力のために+1を与える! –

+0

@BrandonMoore - 私は、AdaTheDevのソリューションは確かに非常にエレガントで、正しい結果を得るために少し調整することができます – GolfWolf

関連する問題