SQL 按位置筛选存储过程日期时间
SQL Stored Procedure datetime filter by location
我在 SQL 服务器中的存储过程有问题,有一个 table 有两个日期时间列,一个开始时间和一个结束时间,我根据位置和实体。
位置报表中,当设置了开始时间和结束时间的过滤条件时,只显示开始时间至少与过滤开始时间一样大且结束时间不晚于过滤条件的位置记录在构建报告时会考虑结束时间。例如,如果实际上 John Doe 从 8:30 到 9:30 在房间 A,然后从 9:30 到 10:30 在房间 B,则报告从 9:00 到 10:00 将不包括 John Doe 行踪的记录。
所需的行为是应该包括在结束时间之前开始并在开始时间之后结束的位置间隔(与单个位置记录相反)。在演示方面,在上述 John Doe 的情况下,输出报告应显示 John Doe 在 A 房间的 9:00 到 9:30 以及在 B 房间的 9:30 到 10:00,当位置间隔的限制不在过滤约束范围内时,施加过滤限制。
这可能吗?如果需要任何其他信息,请告诉我,目前我使用的是基本的 AND locationchangehistory.starttime >= Starttime AND locationchangehistory.endtime <= @Endtime)
这是公司使用的完整存储过程,希望格式正确:-
@Asset Varchar (MAX) = NULL OUTPUT,
@Location Varchar (MAX) = NULL OUTPUT,
@Ward Varchar (MAX) = NULL OUTPUT,
@Zone Varchar (MAX) = NULL OUTPUT,
@Floor Varchar (MAX) = NULL OUTPUT,
@Starttime datetime OUTPUT,
@Endtime datetime OUTPUT,
@Top int,
@FacilityID int
AS
SELECT DISTINCT TOP (@Top)
location.name AS 'Location',
monitoredentity.name AS 'Asset',
zone.name AS 'Zone',
floor.name AS 'Floor',
ward.name AS 'Area',
locationchangehistory.starttime AS 'Starttime',
locationchangehistory.endtime AS 'Endtime',
CONVERT(varchar(max), DATEDIFF(SECOND,
locationchangehistory.starttime, locationchangehistory.endtime) / 3600) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 3600 / 60), 2) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 60), 2) AS 'TimeInPlace'
FROM floor INNER JOIN
zone ON zone.floor = floor.id INNER JOIN
ward ON zone.id = ward.zone INNER JOIN
location ON ward.id = location.ward INNER JOIN
locationchangehistory ON location.id = locationchangehistory.location INNER JOIN
monitoredentity ON monitoredentity.id = locationchangehistory.entity
WHERE
(monitoredentity.type = 4
AND floor.facilityid = @FacilityID
AND zone.facilityid = @FacilityID
AND ward.facilityid = @FacilityID
AND Location.facilityid = @FacilityID
AND locationchangehistory.facility = @FacilityID
AND monitoredentity.facilityid = @FacilityID
AND charindex(',' + cast(monitoredentity.id AS VARCHAR(MAX)) + ',', ',' + @Asset + ',') > 0
AND locationchangehistory.starttime >= @Starttime
AND locationchangehistory.endtime <= @Endtime)
AND ((charindex(',' + cast(Location.id AS VARCHAR(MAX)) + ',', ',' + @location + ',') > 0 OR charindex(',' + cast(Ward.id AS VARCHAR(MAX)) + ',', ',' + @Ward + ',') > 0
OR charindex(',' + cast(zone.id AS VARCHAR(MAX)) + ',', ',' + @Zone + ',') > 0) OR charindex(',' + cast(floor.id AS VARCHAR(MAX)) + ',', ',' + @Floor + ',') > 0)
ORDER by locationchangehistory.starttime DESC`
如果我没猜错,您只需要一个 OR-Opreator。使用 AND 运算符,您希望条件检查两个布尔表达式是否为真。
例如
A = 1 AND B = 1 表示检查 A 是否等于 1,并且当且仅当 A 为真时,检查 B 是否也等于 1 才有用。如果第一个条件不为真,即使它为真,它也不会达到第二个条件。
OR 操作将检查两个条件中的任何一个是否为真,并且 return ROW 如果其中一个条件命中。
我喜欢下面的解释:
- compare AND to a multiplication (*)
- Compare OR to a add operation (+)
- 1 and 0 are our boolean values
- so 0 * 1 = 0 and vice versa but 1*1 = 1
- 1 + 0 = 1, 0+1 and 1+1 = 1
对于示例数据,我在下面创建了 table 并在其中插入了记录。
create table #time_managment
(Empid char(21),Location char(65), timeIN time,OUTtime time)
此处插入。
insert into #time_managment
values('John Doe','Development Room','8:00','8:30')
insert into #time_managment
values('John Doe','INtegration Room','8:40','9:30')
insert into #time_managment
values('John Doe','QA Room','10:00','11:30')
下面选择会显示table和时间范围7:00
到11:00
的所有数据。通过使用 case
我们可以在所需的时间范围内显示 timeout/end 时间。
select * from #time_managment
select Empid,Location,timeIN,
case when OUTTime<'11:00' then
OUTTime
else
'11:00'
end from #time_managment
where timeIN between '7:00' and '11:00'
and OUTtime >=timeIN
刚刚更改了您的 select 和位置,试试这个。
SELECT DISTINCT TOP (@Top)
location.name AS 'Location',
monitoredentity.name AS 'Asset',
zone.name AS 'Zone',
floor.name AS 'Floor',
ward.name AS 'Area',
locationchangehistory.starttime AS 'Starttime',
case when locationchangehistory.endtime<@Endtime then
locationchangehistory.endtime else
@Endtime
end 'Endtime',
CONVERT(varchar(max), DATEDIFF(SECOND,
locationchangehistory.starttime, locationchangehistory.endtime) / 3600) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 3600 / 60), 2) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 60), 2) AS 'TimeInPlace'
FROM floor INNER JOIN
zone ON zone.floor = floor.id INNER JOIN
ward ON zone.id = ward.zone INNER JOIN
location ON ward.id = location.ward INNER JOIN
locationchangehistory ON location.id = locationchangehistory.location INNER JOIN
monitoredentity ON monitoredentity.id = locationchangehistory.entity
WHERE
locationchangehistory.starttime between locationchangehistory.starttime and locationchangehistory.endtime
AND locationchangehistory.endtime >= locationchangehistory.starttime
AND (monitoredentity.type = 4
AND floor.facilityid = @FacilityID
AND zone.facilityid = @FacilityID
AND ward.facilityid = @FacilityID
AND Location.facilityid = @FacilityID
AND locationchangehistory.facility = @FacilityID
AND monitoredentity.facilityid = @FacilityID
AND charindex(',' + cast(monitoredentity.id AS VARCHAR(MAX)) + ',', ',' + @Asset + ',') > 0
--AND locationchangehistory.starttime >= @Starttime
--AND locationchangehistory.endtime <= @Endtime)
AND ((charindex(',' + cast(Location.id AS VARCHAR(MAX)) + ',', ',' + @location + ',') > 0 OR charindex(',' + cast(Ward.id AS VARCHAR(MAX)) + ',', ',' + @Ward + ',') > 0
OR charindex(',' + cast(zone.id AS VARCHAR(MAX)) + ',', ',' + @Zone + ',') > 0) OR charindex(',' + cast(floor.id AS VARCHAR(MAX)) + ',', ',' + @Floor + ',') > 0)
我在 SQL 服务器中的存储过程有问题,有一个 table 有两个日期时间列,一个开始时间和一个结束时间,我根据位置和实体。
位置报表中,当设置了开始时间和结束时间的过滤条件时,只显示开始时间至少与过滤开始时间一样大且结束时间不晚于过滤条件的位置记录在构建报告时会考虑结束时间。例如,如果实际上 John Doe 从 8:30 到 9:30 在房间 A,然后从 9:30 到 10:30 在房间 B,则报告从 9:00 到 10:00 将不包括 John Doe 行踪的记录。
所需的行为是应该包括在结束时间之前开始并在开始时间之后结束的位置间隔(与单个位置记录相反)。在演示方面,在上述 John Doe 的情况下,输出报告应显示 John Doe 在 A 房间的 9:00 到 9:30 以及在 B 房间的 9:30 到 10:00,当位置间隔的限制不在过滤约束范围内时,施加过滤限制。
这可能吗?如果需要任何其他信息,请告诉我,目前我使用的是基本的 AND locationchangehistory.starttime >= Starttime AND locationchangehistory.endtime <= @Endtime)
这是公司使用的完整存储过程,希望格式正确:-
@Asset Varchar (MAX) = NULL OUTPUT,
@Location Varchar (MAX) = NULL OUTPUT,
@Ward Varchar (MAX) = NULL OUTPUT,
@Zone Varchar (MAX) = NULL OUTPUT,
@Floor Varchar (MAX) = NULL OUTPUT,
@Starttime datetime OUTPUT,
@Endtime datetime OUTPUT,
@Top int,
@FacilityID int
AS
SELECT DISTINCT TOP (@Top)
location.name AS 'Location',
monitoredentity.name AS 'Asset',
zone.name AS 'Zone',
floor.name AS 'Floor',
ward.name AS 'Area',
locationchangehistory.starttime AS 'Starttime',
locationchangehistory.endtime AS 'Endtime',
CONVERT(varchar(max), DATEDIFF(SECOND,
locationchangehistory.starttime, locationchangehistory.endtime) / 3600) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 3600 / 60), 2) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 60), 2) AS 'TimeInPlace'
FROM floor INNER JOIN
zone ON zone.floor = floor.id INNER JOIN
ward ON zone.id = ward.zone INNER JOIN
location ON ward.id = location.ward INNER JOIN
locationchangehistory ON location.id = locationchangehistory.location INNER JOIN
monitoredentity ON monitoredentity.id = locationchangehistory.entity
WHERE
(monitoredentity.type = 4
AND floor.facilityid = @FacilityID
AND zone.facilityid = @FacilityID
AND ward.facilityid = @FacilityID
AND Location.facilityid = @FacilityID
AND locationchangehistory.facility = @FacilityID
AND monitoredentity.facilityid = @FacilityID
AND charindex(',' + cast(monitoredentity.id AS VARCHAR(MAX)) + ',', ',' + @Asset + ',') > 0
AND locationchangehistory.starttime >= @Starttime
AND locationchangehistory.endtime <= @Endtime)
AND ((charindex(',' + cast(Location.id AS VARCHAR(MAX)) + ',', ',' + @location + ',') > 0 OR charindex(',' + cast(Ward.id AS VARCHAR(MAX)) + ',', ',' + @Ward + ',') > 0
OR charindex(',' + cast(zone.id AS VARCHAR(MAX)) + ',', ',' + @Zone + ',') > 0) OR charindex(',' + cast(floor.id AS VARCHAR(MAX)) + ',', ',' + @Floor + ',') > 0)
ORDER by locationchangehistory.starttime DESC`
如果我没猜错,您只需要一个 OR-Opreator。使用 AND 运算符,您希望条件检查两个布尔表达式是否为真。
例如
A = 1 AND B = 1 表示检查 A 是否等于 1,并且当且仅当 A 为真时,检查 B 是否也等于 1 才有用。如果第一个条件不为真,即使它为真,它也不会达到第二个条件。
OR 操作将检查两个条件中的任何一个是否为真,并且 return ROW 如果其中一个条件命中。
我喜欢下面的解释:
- compare AND to a multiplication (*)
- Compare OR to a add operation (+)
- 1 and 0 are our boolean values
- so 0 * 1 = 0 and vice versa but 1*1 = 1
- 1 + 0 = 1, 0+1 and 1+1 = 1
对于示例数据,我在下面创建了 table 并在其中插入了记录。
create table #time_managment
(Empid char(21),Location char(65), timeIN time,OUTtime time)
此处插入。
insert into #time_managment
values('John Doe','Development Room','8:00','8:30')
insert into #time_managment
values('John Doe','INtegration Room','8:40','9:30')
insert into #time_managment
values('John Doe','QA Room','10:00','11:30')
下面选择会显示table和时间范围7:00
到11:00
的所有数据。通过使用 case
我们可以在所需的时间范围内显示 timeout/end 时间。
select * from #time_managment
select Empid,Location,timeIN,
case when OUTTime<'11:00' then
OUTTime
else
'11:00'
end from #time_managment
where timeIN between '7:00' and '11:00'
and OUTtime >=timeIN
刚刚更改了您的 select 和位置,试试这个。
SELECT DISTINCT TOP (@Top)
location.name AS 'Location',
monitoredentity.name AS 'Asset',
zone.name AS 'Zone',
floor.name AS 'Floor',
ward.name AS 'Area',
locationchangehistory.starttime AS 'Starttime',
case when locationchangehistory.endtime<@Endtime then
locationchangehistory.endtime else
@Endtime
end 'Endtime',
CONVERT(varchar(max), DATEDIFF(SECOND,
locationchangehistory.starttime, locationchangehistory.endtime) / 3600) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 3600 / 60), 2) + ':' + RIGHT('0' + CONVERT(varchar(2), DATEDIFF(SECOND, locationchangehistory.starttime,
locationchangehistory.endtime) % 60), 2) AS 'TimeInPlace'
FROM floor INNER JOIN
zone ON zone.floor = floor.id INNER JOIN
ward ON zone.id = ward.zone INNER JOIN
location ON ward.id = location.ward INNER JOIN
locationchangehistory ON location.id = locationchangehistory.location INNER JOIN
monitoredentity ON monitoredentity.id = locationchangehistory.entity
WHERE
locationchangehistory.starttime between locationchangehistory.starttime and locationchangehistory.endtime
AND locationchangehistory.endtime >= locationchangehistory.starttime
AND (monitoredentity.type = 4
AND floor.facilityid = @FacilityID
AND zone.facilityid = @FacilityID
AND ward.facilityid = @FacilityID
AND Location.facilityid = @FacilityID
AND locationchangehistory.facility = @FacilityID
AND monitoredentity.facilityid = @FacilityID
AND charindex(',' + cast(monitoredentity.id AS VARCHAR(MAX)) + ',', ',' + @Asset + ',') > 0
--AND locationchangehistory.starttime >= @Starttime
--AND locationchangehistory.endtime <= @Endtime)
AND ((charindex(',' + cast(Location.id AS VARCHAR(MAX)) + ',', ',' + @location + ',') > 0 OR charindex(',' + cast(Ward.id AS VARCHAR(MAX)) + ',', ',' + @Ward + ',') > 0
OR charindex(',' + cast(zone.id AS VARCHAR(MAX)) + ',', ',' + @Zone + ',') > 0) OR charindex(',' + cast(floor.id AS VARCHAR(MAX)) + ',', ',' + @Floor + ',') > 0)