這裏是一個查詢,將給予每個計費週期,最高可達65,535計費時段,精確到秒。
我的解決方案使用計算出的「Tally」表,但從長遠來看,您最好在數據庫中創建自己的物理「Tally」表。有關更多詳細信息,請參見What is the best way to create and populate a numbers table?。
您應該可以用您的巡視表替換@tblPatrols
。
DECLARE @tblPatrols TABLE (alertNo int, startTime datetime);
DECLARE @hoursPerBillingPeriod int, @toHoursConversion float;
SET @hoursPerBillingPeriod = 12;
SET @toHoursConversion = 60 * 60;
INSERT INTO @tblPatrols (alertNo, startTime)
VALUES
(1, '2016-01-28 05:57')
, (1, '2016-01-28 07:23')
, (1, '2016-01-28 08:10')
, (2, '2016-01-28 09:05')
, (2, '2016-01-28 12:22')
, (2, '2016-01-28 16:06')
, (2, '2016-01-28 23:45')
, (2, '2016-01-29 00:05')
, (3, '2016-01-28 12:00')
, (3, '2016-01-28 16:06')
, (3, '2016-01-29 00:00')
, (4, '2016-01-28 12:00')
, (4, '2016-01-28 16:06')
, (4, '2016-01-28 23:59:59.997')
;
;WITH
--......................
--This section used to simulate a "Tally" table... you would be better off to Create a physical Tally table
-- see: https://stackoverflow.com/questions/1393951/what-is-the-best-way-to-create-and-populate-a-numbers-table
Pass0 as (select 1 as C union all select 1) --2 rows
, Pass1 as (select 1 as C from Pass0 as A, Pass0 as B) --4 rows
, Pass2 as (select 1 as C from Pass1 as A, Pass1 as B) --16 rows
, Pass3 as (select 1 as C from Pass2 as A, Pass2 as B) --256 rows
, Pass4 as (select 1 as C from Pass3 as A, Pass3 as B)--65536 rows
, Tally as (select row_number() over(order by C) - 1 as N from Pass4) --65536 rows
--........................
,cteNumBillings as (
SELECT fp.alertNo
, firstPatrolTime = min(fp.startTime)
, lastPatrolTime = max(fp.startTime)
, hoursBetweenStartMinMax = datediff(second, min(fp.startTime), max(fp.startTime))/@toHoursConversion
, numberOfBillingPeriods = floor(((datediff(second, min(fp.startTime), max(fp.startTime))/@toHoursConversion)/@hoursPerBillingPeriod) + 1)
FROM @tblPatrols fp
GROUP BY fp.alertNo
)
SELECT b.alertNo
--This is the "x" value of the expression "Billing Period x of y"
, BillingPeriodNumber = t.N + 1
, BillingPeriodPatrolCount =
(select count(*)
from @tblPatrols p
where p.alertNo = b.alertNo
and p.startTime >= dateadd(hour, 12 * t.N, b.firstPatrolTime)
and p.startTime < dateadd(hour, 12 * (t.N+1), b.firstPatrolTime)
)
, BillingStart = dateadd(hour, 12 * t.N, b.firstPatrolTime)
, BillingEnd = dateadd(second, -1, dateadd(hour, 12 * (t.N + 1), b.firstPatrolTime))
--This is the "y" value of the expression "Billing Period x of y"
, TotalBillingPeriodCount = b.numberOfBillingPeriods
FROM cteNumBillings b
INNER JOIN Tally t ON t.N >= 0 and t.N < b.numberOfBillingPeriods
ORDER BY 1,2
;
看看您的需求,似乎要決定巡邏隊是開始新的結算任務還是屬於之前的任務,您需要查看先前的所有巡邏和職責(如果巡邏總是從0開始,這可能是固定的:00/12:00)。因此,我認爲你不應該嘗試在SQL Server中做到這一點,我建議你在一個單獨的應用程序中做這個異步。 –
嗯,我可以用VBA解決它,但是它必須在服務器端完成,它應該創建一個插入另一個表的結果記錄。巡邏隨時開始,警報號碼是客戶的一種訂單,可能會持續幾天甚至更長時間。 – mak
tblAllPatrols有沒有結束時間?如果沒有,那麼你怎麼知道巡邏隊何時結束? – BateTech