SQL计数不同的时间,相差30分钟

SQL计数不同的时间,相差30分钟,sql,datetime,time,count,distinct,Sql,Datetime,Time,Count,Distinct,我试图找到一个SQL查询,它将计算至少30分钟不同的不同开始时间的数量 我有一些员工在一周内至少三次不同的时间开始工作时会获得积分,其中开始时间与其他开始时间至少不同30分钟。 例如: select count(distinct (CONVERT(VARCHAR(10), starttime, 108))), employeecode from schedule where CONVERT(VARCHAR(10), starttime, 108) >= (select min(CONV

我试图找到一个SQL查询,它将计算至少30分钟不同的不同开始时间的数量

我有一些员工在一周内至少三次不同的时间开始工作时会获得积分,其中开始时间与其他开始时间至少不同30分钟。 例如:

select count(distinct (CONVERT(VARCHAR(10), starttime, 108))), employeecode
from schedule 
where CONVERT(VARCHAR(10), starttime, 108) >= 
(select min(CONVERT(VARCHAR(10), dateadd (mi, 30, s2.starttime), 108)) from schedule s2)  
group by starttime, employeecode
我希望得到一个结果与员工代码和不同的数字和不同的开始时间。例如,员工代码=9999,不同的开始时间=4 我一直在摸索这一点,但还没有得到一些工作

有人能告诉我哪里出了问题,或者一个合适的解决方案可以帮助我吗?
提前感谢您的帮助:)

[更新:根据海报在对该答案的评论中对问题的澄清,我用该答案解决的问题显然不是海报试图解决的问题。我留下答案是为了展示其他问题的解决方案,而不是删除澄清问题陈述的评论]

将问题分为两部分:确定“唯一”(30分钟内)开始,然后计数。第一部分是我认为您遇到问题的部分。以下是一种方法:

SELECT employeecode, starttime FROM schedule S1
    WHERE NOT EXISTS (SELECT * FROM schedule S2 
        WHERE S2.employeecode = S1.employeecode AND
              S2.starttime > DATEADD(mi, -29, S1.starttime)
请注意:

  • 我从原始查询中复制了日期数学逻辑,而不是查找语法

  • 我想starttime是DATETIME

  • 我用了29分钟,这样,如果开始时间相隔30分钟或更长时间,他们就可以得到奖金(如你的问题陈述中所述)。实际上,你应该用秒和减法(29*60)+59来计算日期。我的版本比你的问题陈述中指定的对员工更慷慨

  • 您可以将此查询封装在视图或内部查询中,并执行以下操作(假设它是视图):

    从“唯一开始”视图中选择employeecode,count() 其中开始时间介于(期初)和(期末)之间 按COUNT()>=3的员工代码分组

  • notexists技术可能很慢,因此最好将查询限制在您感兴趣的时间段内


在等待确切要求的澄清时,我想我会建议另一种方法。我会给出它的优缺点

如果开始时间通常在某个时间或某个时间附近(您的示例总是在半小时或小时内),那么您可以将所有开始时间拆分为他们所在的“波段”,然后计算不同波段的数量

例如00:00-00:30=波段1 00:30-01:00=波段2 ... 07:00-07:30=波段15 ... 23:30-00:00=波段48

要得到乐队,你只需要一个简单的(尽管相当长)案例陈述

这种方法的主要问题是,当你的时间接近临界值时,它会下降。例如07:29和07:31将在两个不同的波段中,但实际上只有2分钟的间隔。如果你在大约同一时间开始,让波段在每小时15分钟和45分钟后开始和结束,这可以稍微缓解。如果他开始的时间都在乐队的中间,那么你会得到它大部分是正确的…< / P> 但在我看来,这个问题并不真正适合SQL,所以如果你能用另一种语言来做,可能会更好

您可能可以在SQL中使用一些复杂的连接来完成它,但我无法为它编写可靠的SQL…虽然您希望执行以下操作,但从算法上来说

1) 选择一天中最早的开始时间,并称之为你的第一个开始时间。 2) 选择比上一步至少晚30分钟的下一个最早时间。 3) 重复步骤2,直到时间用完。 4) 数数次数


从SQL的角度来看,这个问题是它试图基于前一行创建数据,这意味着使用游标循环时间并将内容存储在变量中。

我假设您的数据库产品是基于OP的SQL Server,但您没有提到版本。如果您使用SQL Server 2005及更高版本您可以尝试以下操作:

With StartTimes As
    (
    Select StartDateTime 
        , Row_Number() Over( Order By StartDateTime ) As Seq 
        , DatePart(hh, StartDateTime) * 60 + DatePart(mi, StartDateTime) As Minutes
    From Schedule
    )
Select *
From StartTimes As S1
Where Exists(
            Select 1
            From StartTimes As S2
            Where S1.Seq <> 1
                And Abs(S2.Minutes - S1.Minutes) >= 30
            )
,起始时间为
(
选择StartDateTime
,行号()在(按开始日期时间排序)上方,如下所示
,DatePart(hh,StartDateTime)*60+日期部分(mi,StartDateTime)作为分钟
按计划
)
挑选*
从StartTimes开始为S1
哪里有(
选择1
从StartTimes到S2
式中S1.序号1
和Abs(S2.5分钟-S1.5分钟)>=30
)
使用Chris提到的时间段(不要与时间强盗混淆):

CREATE TABLE Start_Periods
(
    begin_time    TIME        NOT NULL,
    end_time      TIME        NOT NULL,
    time_period   TINYINT     NOT NULL
    CONSTRAINT PK_Start_Periods PRIMARY KEY CLUSTERED (begin_time),
    CONSTRAINT CK_Start_Periods_begin_before_end CHECK (begin_time < end_time OR end_time = '00:00:00.000')
)
INSERT INTO Start_Periods (begin_time, end_time, time_period)
SELECT '00:00:00.000', '00:15:00.000', 1 UNION ALL
SELECT '00:15:00.000', '00:45:00.000', 2 UNION ALL
SELECT '00:45:00.000', '01:15:00.000', 3 UNION ALL
SELECT '01:15:00.000', '01:45:00.000', 4 UNION ALL
SELECT '01:45:00.000', '02:15:00.000', 5 UNION ALL
SELECT '02:15:00.000', '02:45:00.000', 6 UNION ALL
SELECT '02:45:00.000', '03:15:00.000', 7 UNION ALL
SELECT '03:15:00.000', '03:45:00.000', 8 UNION ALL
--...
SELECT '23:15:00.000', '23:45:00.000', 48 UNION ALL
SELECT '23:45:00.000', '00:00:00.000', 1
CREATE TABLE Start\u Periods
(
开始时间时间不为空,
结束时间时间不为空,
时间段TINYINT不为空
约束主键开始时间主键聚集(开始时间),
约束检查结束检查之前的开始时间(开始时间<结束时间或结束时间='00:00:00.000')
)
插入开始时段(开始时段、结束时段、时段)
选择“00:00:00.000”、“00:15:00.000”,1个联合所有
选择'00:15:00.000','00:45:00.000',2个UNION ALL
选择'00:45:00.000','01:15:00.000',3个UNION ALL
选择'01:15:00.000','01:45:00.000',4个UNION ALL
选择“01:45:00.000”、“02:15:00.000”和“全部5”
选择'02:15:00.000','02:45:00.000',6全部
选择'02:45:00.000','03:15:00.000',7联合所有
选择“03:15:00.000”、“03:45:00.000”和“8全部”
--...
选择“23:15:00.000”、“23:45:00.000”和“48联合所有”
选择“23:45:00.000”、“00:00:00.000”,1
然后,您的查询变成:

SELECT
    SCH.employee_code,
    COUNT(DISTINCT SP.time_period) AS different_time_starts
FROM
    Schedule SCH
INNER JOIN Start_Periods SP ON
    SP.begin_time <= SCH.start_time AND
    SP.end_time > SCH.start_time
GROUP BY
    SCH.employee_code
选择
SCH.employee_代码,
当不同的时间开始时计数(不同的SP时间段)
从…起
附表SCH
内部联接开始\u周期SP打开
SP.开始时间SCH.开始时间
分组
SCH.employee_代码

只是给你一个想法:

  • 构建SQL只需一周