tally table을 사용하여 레코드를 시간당 하나의 레코드로 분할 할 수 있습니다. 예를 들어
다음 대여
RentalId CustomerId Start Finish Cost
-------- ---------- --------------- --------------- ----
1 1 1/1/2016 1:30pm 1/1/2016 4:45pm
이 함께
RentalId Start Finish Cost
-------- --------------- --------------- ----
1 1/1/2016 1:30pm 1/1/2016 2:00pm 1
1 1/1/2016 2:00pm 1/1/2016 3:00pm 2
1 1/1/2016 3:00pm 1/1/2016 4:00pm 3
1 1/1/2016 4:00pm 1/1/2016 4:45pm 4
으로 집계하여 처리되고, 각 레코드 전처리의 비용을 계산할 수있다. 모든 기록이 1 시간 동안 지속 된 것은 아니므로 분당 요금을 사용해야합니다.
그런 다음이 비용을 대여로 그룹화하고 각 대여 비용을 계산하면됩니다.
다음은 완벽한 해결책입니다.
집계 테이블과 전처리 된 레코드에 CTE을 사용했습니다.
;WITH
N0(_) AS (SELECT NULL UNION ALL SELECT NULL),
N1(_) AS (SELECT NULL FROM N0 AS L CROSS JOIN N0 AS R),
N2(_) AS (SELECT NULL FROM N1 AS L CROSS JOIN N1 AS R),
N3(_) AS (SELECT NULL FROM N2 AS L CROSS JOIN N2 AS R),
Tally AS (SELECT N = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM N3 AS L CROSS JOIN N3 AS R),
PreprocessedData AS (SELECT Rent.RentalId,
BillingStart =(CASE WHEN Tally.N = 1 THEN
Rent.Start
ELSE
DATEADD(HOUR, DATEDIFF(HOUR, 0, DATEADD(HOUR, Tally.N - 1, Rent.Start)), 0)--Trim exceeding minutes
END),
BillingEnd = ( CASE WHEN DATEDIFF(HOUR, Rent.Start, Rent.Finish) < Tally.N THEN
Rent.Finish
ELSE
DATEADD(HOUR, DATEDIFF(HOUR, 0, DATEADD(HOUR, Tally.N, Rent.Start)), 0)--Trim exceeding minutes
END),
Rate.HourlyRate
FROM Rentals AS Rent
INNER JOIN Tally ON DATEDIFF(HOUR, Rent.Start, Rent.Finish) >= Tally.N - 1 -- DATEADD(HOUR, Tally.N, Rent.Start) < Rent.Finish
LEFT JOIN Rates AS Rate ON DATEPART(DW, DATEADD(HOUR, Tally.N - 1, Rent.Start)) = Rate.DayNumber
AND DATEPART(HOUR, DATEADD(HOUR, Tally.N - 1, Rent.Start)) = Rate.HourNumber
)
UPDATE Rentals
SET Cost = CalculateCostPerRental.CalculateCost
FROM Rentals
INNER JOIN (SELECT RentalId,
CalculateCost = SUM(HourlyRate * DATEDIFF(MINUTE, BillingStart, BillingEnd) /60)
FROM PreprocessedData
GROUP BY RentalId
HAVING SUM(CASE WHEN HourlyRate IS NOT NULL THEN 0 ELSE 1 END) = 0 /*Update only if all the rates where found*/) AS CalculateCostPerRental ON Rentals.RentalId = CalculateCostPerRental.RentalId
/*cost is null when there is a rate missing in rate table*/
성능은 성능이 좋지 않지만 데이터베이스 디자인 때문입니다. 디자인을 변경하지 않으면이 솔루션이하는 것보다 더 잘 할 수 없을 것입니다. 그러나이 작업을 수행하는 데 정말로 성능이 필요한 경우 문제가됩니다.
면책 조항 : 모든 엣지 케이스를 테스트하지 않았으므로 프로덕션 환경에서 사용하기 전에 일부 테스트를 수행해야합니다. 또한 요금 테이블에 누락 된 요금이있을 수 있습니다.
24 시간 형식의 'HourNumber'가 적용됩니까? '오전 4시'의 비율이 오전 4시, 오후 4시에 적용된다고 가정 해보십시오. 아니면 둘다? –
비용을 계산하려면 대여 기간 전체의 시작 요율을 사용하거나 임대 기간의 모든 특정 시간에 적용되는 요율을 사용 하시겠습니까? – AXMIM
@JoshPart'datepart (시, 시작)'은 오전 4시에 4를, 오후 4시에 16을 반환합니다. –