【问题标题】:SQL Stored Procedure datetime filter by locationSQL 存储过程日期时间按位置过滤
【发布时间】:2015-02-13 19:51:53
【问题描述】:

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

在位置报告中,当设置了开始时间和结束时间的过滤条件时,只有开始时间至少与过滤开始时间一样大且结束时间不晚于过滤结束时间的位置记录在构建报告时考虑。例如,如果实际上 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

这是公司正在使用的完整存储过程,我希望格式正确:-

                     @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`

【问题讨论】:

    标签: sql sql-server datetime filter


    【解决方案1】:

    刚刚更改了您的选择和位置,试试这个。

    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)
    

    【讨论】:

    • 您最好编辑现有答案并将其添加到其中,而不是对同一问题有 2 个答案。
    • 非常感谢这正是我所追求的,感谢大家的帮助!!
    【解决方案2】:

    如果我没看错,你只需要一个 OR-Opreator。使用 AND 运算符,您希望条件检查两个布尔表达式是否为真。

    例如

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

    OR 操作将检查两个条件中的任何一个是否为真,如果其中一个条件命中则返回 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 
    

    【讨论】:

    • 我忘记了 0*0 = 0 和 0+0 = 0
    【解决方案3】:

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

    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
    

    【讨论】:

    • 我希望你现在看起来更好,Tanner。
    猜你喜欢
    • 2021-09-01
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 2013-10-20
    • 1970-01-01
    • 2011-01-25
    • 1970-01-01
    • 2021-04-30
    相关资源
    最近更新 更多