SQL Подсчет разных таймфреймов за известный период - PullRequest
3 голосов
/ 25 февраля 2011

Как я могу считать непрерывные таймфреймы

Мои данные выглядят так:

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 для поиска начальной даты работает только для одного кадра. Вы не можете найти второй / третий кадр с макс.

Есть ли кто-нибудь со свежими новыми идеями?

Ответы [ 3 ]

2 голосов
/ 25 февраля 2011

Я не уверен в причинах полей ID и em_name, поэтому я буду рассматривать его так, как если бы идентификатора было достаточно для использования отдельно.

Я использую логику просто так ... Группа может быть представлена ​​последней записью в группе. И последняя запись - это просто запись, у которой нет соответствующей записи на следующий день.

При условии, что существует индекс для (ID, Em_Reg_Date), это должно быть довольно быстро.

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

Это изменяет логику для просмотра «до следующего понедельника», если текущая запись - пятница, суббота или воскресенье.

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
2 голосов
/ 25 февраля 2011

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 (), но вам потребуется некоторая вариация для расчета начальной даты

1 голос
/ 25 февраля 2011
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

...