我有一个记录表,在SQL Server 2008R2中保存警卫巡逻。
每当值班开始时,都会创建一个新的警报号码,并在此警报号码内进行巡逻并开始时间。
每12个小时,我们可以在至少进行一次巡逻时收取统一费率。当在相同的警报号码下超过12小时范围时,必须再计算一个固定费率。
12小时的计算从第一次巡逻的时间开始。
我尝试使用临时表但到目前为止无法解决它。
DECLARE @t1 TABLE (
AlertNo INT,
Starttime SMALLDATETIME,
Endtime SMALLDATETIME
)
INSERT INTO @t1 (AlertNo, Starttime, Endtime)
SELECT AlertNo,
Starttimepatrol,
DATEADD(HOUR, 12, Starttimepatrol)
FROM tblAllPatrols
WHERE PatrolNo = 1
SELECT AlertNo,
(
SELECT COUNT(*)
FROM [tblAllPatrols] a
INNER JOIN @t1 b ON b.AlertNo = a.AlertNo
WHERE a.Starttimepatrol BETWEEN b.Starttime AND b.Endtime
) AS patrols
FROM [vwAlleDatensaetze]
GROUP BY AlertNo
我知道这不是故事的结尾,但由于我甚至无法计算巡逻次数,因此我无法找到解决问题的方法。
它应以某种方式将每个警报号码的12小时范围内的巡逻“分组”,然后计算在同一警报号码下存在多少组。
希望,你们中的某个人可以引导我得到我需要的结果。
谢谢你的帮助 迈克尔
答案 0 :(得分:0)
试试这个,它假设在第一次巡逻后,结算周期是此时间的8小时的倍数:
MS SQL Server 2008架构设置:
查询1 :
DECLARE @Patrols TABLE
(
AlertNo INT IDENTITY PRIMARY KEY,
StartTime DateTime
)
INSERT INTO @Patrols (StartTime)
VALUES ('20160126 09:57'),
('20160126 10:21'),
('20160126 19:54'),
('20160126 23:21'),
('20160127 08:13'),
('20160127 16:43'),
('20160128 07:33')
;WITH FirstBillingPeriodCTE
AS
(
SELECT MIN(StartTime) as BillingStartTime,
DateAdd(HOUR, 12, MIN(StartTime)) As BillingEndTime,
1 As BillingPeriod
FROM @Patrols
),
Numbers
As
(
SELECT num
FROM (Values (0),(1), (2), (3), (4), (5), (6), (7), (8), (9)) AS n(Num)
),
BillingPeriodsCTE
AS
(
SELECT DATEADD(Hour, 8 * (BillingPeriod + Numbers.Num), BillingStartTime) AS BillingStartTime,
DATEADD(Hour, 8 * (BillingPeriod + Numbers.Num), BillingEndTime) AS BillingEndTime,
BillingPeriod + Numbers.Num As BillingPeriod
FROM FirstBillingPeriodCTE
CROSS JOIN Numbers
)
SELECT COUNT(DISTINCT BillingPeriod)
FROM @Patrols P
INNER JOIN BillingPeriodsCTE B
ON P.StartTime >= B.BillingStartTime AND P.StartTime < B.BillingEndTime
<强> Results 强>:
| |
|---|
| 4 |
答案 1 :(得分:0)
以下是一个查询,它将为每个结算周期提供最多65,535个结算周期,精确到秒。
我的解决方案使用计算的&#34; Tally&#34;桌子,但从长远来看,你会更好地创造自己的体力&#34; Tally&#34;数据库中的表。有关详细信息,请参阅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
;
答案 2 :(得分:0)
我自己找到了一个解决方案,这似乎更容易,我找不到使用它的任何错误。 我在变量中进行第一次巡逻的第一次Startime。然后我使用datediff将所有StartTimePatrol的差异与第一次巡逻的startime区分开来并将其除以12小时
set @BillingPeriod=(select (datediff(hour,@StartTime,@StartTimePatrol)/12)+1)
然后我将每个记录的结果放在临时表
中insert into @t2 ( Alertno, Starttime, Billings )
values ( @Alertno, @StartTimePatrol, @BillingPeriod )
然后我将altertno和Billings分组并计算它们
select alertno, count(Billings ) from (select alertno, Billings from @t2
group by alertno, Billings ) temp group by alertno
结果对我来说是正确的。
感谢所有回复。 迈克尔