SQL存储过程datetime按位置过滤

时间:2015-02-13 08:27:57

标签: sql sql-server datetime filter

我在SQL Server中遇到存储过程的问题,有一个包含两个日期时间列的表,一个我根据位置和实体过滤的开始时间和结束时间。

在位置报告中,当设置了开始时间和结束时间的过滤条件时,只有开始时间至少与过滤开始时间和结束时间一样大的位置记录不晚于过滤结束时间在构建报告时考虑。例如,如果实际上John Doe从8:30到9:30在A室,然后在9:30到10:30在B室,从9:00到10:00的位置报告将不包括John Doe的下落。

期望的行为是应该包括在结束时间之前开始并在开始时间之后结束的位置间隔(与个别位置记录相对)。在演示方面,在上面的John Doe的情况下,输出报告应该在9:00到9:30之间在房间A中显示John Doe,在9:30到10:00在房间B中显示过滤限制。位置间隔的限制不在过滤约束内。

这一切都可能吗?如果还有其他需要的信息,请告诉我,目前我正在使用基本的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`

3 个答案:

答案 0 :(得分:0)

如果我找到了你,你只需要一个OR-Opreator。使用AND运算符,您希望条件检查BOTH布尔表达式为真。

E.g。

A = 1 AND B = 1表示检查A是否等于1以及是否且仅当A为真时,检查B是否也等于1也是有用的。如果第一个条件不成立,它就不会达到第二个条件,即使它是真的。

如果两个条件中的任何一个为真,则OR操作将检查,如果其中一个条件有命中,则返回ROW。

我以某种方式喜欢以下的eplanation:

- 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 

答案 1 :(得分:0)

对于样本数据,我创建了下表并在其中插入记录。

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')

以下选项将显示表格中的所有数据以及时间范围为7:0011:00的数据。通过使用case,我们可以在所需的时间范围内显示超时/结束时间。

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

答案 2 :(得分:0)

刚刚更改了您的选择和位置,请尝试此操作。

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)