我在SQL Server 2008R2中有一個價目表,並且想根據服務的時間計算服務的價格。計算價格表中的時間
timefrom |timeto |Price
-------- |------ |-----
1900-01-01 00:00:00|1900-01-01 07:00:00|20.00
1900-01-01 07:00:00|1900-01-01 19:00:00|15.00
1900-01-01 19:00:00|1900-01-02 00:00:00|20.00
此價目表顯示開始於19:00在夜間不同的價格,並一直持續到上午07時和白天從07:00至19:00。
分鐘必須四捨五入到四分之一小時。 還有一些需要照顧的地方,例如最低限度通知Periode(@Vorlaufzeit)以及週末週末。這兩個條件都得到滿足,而不是問題。我的問題是第一個和最後一個記錄,我必須舍入和/或舍入,這是不正確的。兩行都有1個循環,並且應該在兩次更新中都正確糾正,但不是。
因此,例如服務從2016-11-04 10:50(四捨五入到10:45即0.25小時)到2016-11-04 19:25(四捨五入到19:30爲0.5小時)爲0.25 + 8 + 0.5 = 8.75小時,成本爲8.25 * 15 + 0.5 * 20 = 133.75。
我試過這段代碼,但它並沒有給我帶來正確的結果。這只是第一個和最後一個我必須舍入或倒下的記錄。這是正確的,當有充足的時間。
DECLARE @Dauer int
DECLARE @X int --Loopcounter für Stunden
declare @Y int --Loopcounter für Tageszahler
declare @Anfangszeit datetime
declare @Anfangsstunde datetime
declare @Endzeit datetime
declare @Vorlaufzeit int --in Minuten
declare @ErsteZeitvon datetime
declare @SummeAnzStunden decimal(8,2)
declare @MinimumZeit int
declare @ZeitvonVolleStunde int -- aus 07:25 mach 7 Uhr
declare @ZeitbisVolleStunde int
declare @AnfangsDatumZeit as datetime
declare @EndDatumZeit as datetime
declare @AnfangsDatumZeitLoop as datetime
declare @AnfangsZeitLoop as datetime
declare @TagesZaehler int
set @AnfangsDatumZeit = @[email protected]
set @EndDatumZeit = @[email protected]
set @Tageszaehler=datediff(day,@AnfangsDatumZeit, @EndDatumZeit)
declare @t1 table (PreisID int, AnzStunden decimal(5,2), Preis decimal(8,2), Anfangszeit datetime, Prüfzeit datetime, startzeit datetime, endezeit datetime, Vorlaufzeit int, Dauer int, PreisFT decimal(8,2), DatZeitvon datetime, DatZeitbis datetime, Tageszaehler int)
-- Insert statements for procedure here
set @ZeitvonVolleStunde=Datediff(hour, '00:00:00', @Zeitvon)
set @ZeitbisVolleStunde=Datediff(minute, '00:00:00', @Zeitbis)
set @Dauer=ceiling(Datediff(minute, @AnfangsDatumZeit, @EndDatumZeit)/60.00)
set @Vorlaufzeit=datediff(minute,@Bestelldatum, @AnfangsDatumZeit)
SET @X = 0
if Datediff(minute, @AnfangsDatumZeit, @EndDatumZeit) > 360
begin
WHILE (@X <[email protected]) --z.b. 13
begin
--set @Y = datediff(day,@AnfangsDatumZeit,@AnfangsDatumZeitLoop)
set @Y = datediff(day,@AnfangsDatumZeit,dateadd(hour,@X, @AnfangsDatumZeit))
set @AnfangsDatumZeitLoop=dateadd(hour,@X, @AnfangsDatumZeit)
set @AnfangsZeitLoop=dateadd(hour,@X, @Zeitvon)
insert into @t1 (PreisID, AnzStunden, Preis , Anfangszeit, Prüfzeit, DatZeitvon , DatZeitbis )
SELECT top 1 preisID, 1, Preis, @AnfangsZeitLoop, @AnfangsDatumZeitLoop, Zeitvon, Zeitbis
FROM dbo.Mypricetable
where [email protected] --SdlID
and Wochentag=case when DATEPART(dw,@AnfangsDatumZeitLoop) < 6 then 'W' else 'S' end --Wochentag
and @Vorlaufzeit BETWEEN Vorlaufzeitvon and Vorlaufzeitbis --Vorlaufzeit in Minuten
AND @Dauer*60 BETWEEN Dauervon AND Dauerbis --DauerInMinuten
and @AnfangsZeitLoop between Zeitvon and Zeitbis --sucht die von/bis Zeitgruppe
order by zeitvon
SET @X = @X + 1
end
--check and udate of the first record in @t1 rounding down to 15 minutes
update @t1 set Anzstunden= Anzstunden + CONVERT(DECIMAL(6, 2), ROUND(((datediff(minute,[dbo].[sfRoundToHourParts](@AnfangsDatumZeit,1), [dbo].[sfRoundToHourParts](@AnfangsDatumZeit,4)) + 7)/60.00)/25, 2) * 25)
from @t1 c where c.Prüfzeit=(SELECT Top 1 Prüfzeit from @t1 order by Prüfzeit)
--check and udate of the last record in @t1 rounding up to 15 minutes
update @t1 set Anzstunden= round(convert(decimal(5,2),datepart(minute,@EndDatumZeit)+7)/60/25,2)*25
from @t1 c where c.Prüfzeit=(SELECT Top 1 Prüfzeit from @t1 order by Prüfzeit DESC)
end
select * from @t1 order by Prüfzeit
感謝您的幫助! 邁克爾
你爲什麼用'datetime'而不是'time'? –
@PanagiotisKanavos在做了類似的事情之後,'time'無法表達24小時(或更多),使得午夜時間跨越噩夢處理的範圍。檢查RangeStart <= Target <= RangeEnd'變成類似'(RangeStart <= Target和Target <= RangeEnd)或(RangeStart> RangeEnd和(RangeStart <= Target或Target <= RangeEnd))'。如果測試並隱藏在UDF中,則不會太糟糕,但散佈時會出現笨拙和容易出錯的情況。 – HABO
@HABO不在這種情況下。這只是一天的幾個小時。儘管如此,這裏的問題還是比較嚴重,包括試圖循環而不是寫一個適當的查詢 –