3

我如何计算连续的时间范围

我的数据如下所示:

Id| Em_Name|Em_Reg_Date
--------------------------------
1 | John   |2010-03-30 00:00:00  
1 | John   |2010-03-31 00:00:00  
2 | Marc   |2010-10-26 00:00:00  
2 | Marc   |2010-10-27 00:00:00  
2 | Marc   |2010-10-28 00:00:00  
2 | Marc   |2010-10-29 00:00:00  
2 | Marc   |2010-12-16 00:00:00  
2 | Marc   |2010-12-17 00:00:00    
2 | Marc   |2010-12-20 00:00:00  
2 | Marc   |2010-12-21 00:00:00  
2 | Marc   |2010-12-22 00:00:00  
3 | Paul   |2010-02-25 00:00:00  
3 | Paul   |2010-02-26 00:00:00  
3 | Paul   |2010-12-13 00:00:00  
3 | Paul   |2010-12-14 00:00:00  
3 | Paul   |2010-12-15 00:00:00  
--------------------------------

时间范围是一个连续的时间段。
例如,保罗有以下两 (2) 个时间框架

 FRAME 1 FROM 2010-02-25 00:00:00  to 2010-02-26 00:00:00  
 FRAME 2 FROM 2010-12-13 00:00:00  to 2010-12-15 00:00:00  

所以,结果应该是这样的

1 John   1  
2 Marc   3  
3 Paul   2  

问题是:我需要计算每个员工的时间框架。

这里的问题在于我需要隔离持续的时间范围以计算它们。我什至尝试过声明游标(有效,但我必须将数据存储在临时表中)并且我希望它在一个“简单”的 sql 语句中使用 max 查找开始日期仅适用于一帧。您找不到最大的第二/第三帧。

有没有人有新鲜的想法?

4

3 回答 3

2

I'm not sure of the reason for both the ID and em_name fields, so I'll treat it as if the ID is sufficient to use alone.

The logic I'm using is simply this... A group can be represented by the last entry in the group. And the last entry is simply an entry that does not have a matching entry for the following day.

Provided that an Index for (ID, Em_Reg_Date) exists, this should be quite fast.

SELECT
  ID,
  COUNT(*)
FROM
  your_table [source]
WHERE
  NOT EXISTS (
              SELECT
                *
              FROM
                your_table
              WHERE
                Em_Reg_Date = [source].Em_Reg_Date + 1
                AND ID = [source].ID
             )
GROUP BY
  ID


EDIT

This changes the logic to look "up to the next monday" if the current record is a Friday, Saturday or Sunday.

SET DATEFIRST 1   -- This just ensures that Monday is counted as Day 1

SELECT
  ID,
  COUNT(*)
FROM
  your_table [source]
WHERE
  NOT EXISTS (
              SELECT
                *
              FROM
                your_table
              WHERE
                ID = [source].ID
                AND Em_Reg_Date <= [source].Em_Reg_Date + CASE WHEN DATEPART(weekday, [source].Em_Reg_Date) >= 5 THEN 8 - DATEPART(weekday, [source].Em_Reg_Date) ELSE 1 END
                AND Em_Reg_Date >  [source].Em_Reg_Date
             )
GROUP BY
  ID
于 2011-02-25T13:16:01.493 回答
2

SQL Server 2005+

select em_name, COUNT(distinct startdate)
from
(
    select *, startdate = em_reg_date - ROW_NUMBER() over (
        partition by em_name order by em_reg_date) +1
    from tbl
) X
group by Em_Name

Oracle、DB2 也支持 Row_Number(),但您需要一些变化来计算 startdate

于 2011-02-25T13:06:49.730 回答
1
SELECT Id, Name, COUNT( Id )
FROM (
   SELECT Id, Name
   FROM  `<your_table_name>` 
   GROUP BY Name, MONTH( Em_Reg_Date )
   ) as X
GROUP BY Id

在 MySQL 5.0.7 上测试

于 2011-02-25T13:38:15.450 回答