Установить основанный способ классификации строк на основе дат, подходящих в скользящем двухчасовом окне - PullRequest
1 голос
/ 05 июня 2010

Итак, у меня есть набор данных, который включает столбец дат и столбец идентификатора. Вот пример данных даты:

5/30/10 12:00 AM
5/30/10 12:01 AM
5/30/10 1:59 AM
5/30/10 1:59 AM
5/30/10 3:58 AM
5/30/10 3:58 AM
5/30/10 5:57 AM
5/30/10 6:57 AM
5/30/10 7:56 AM
5/30/10 7:56 AM
5/30/10 9:55 AM
5/30/10 11:54 AM

То, что я хотел бы сделать, это создать сегменты для этих строк на основе параметра типа «2 часа». Эти двухчасовые окна начинаются с самой ранней даты в наборе данных, но переходят к следующему времени запуска, когда вы просматриваете список. Например, ожидаемый вывод «buckets» для моего списка будет:

5/30/10 12:00 AM  1
5/30/10 12:01 AM  1
5/30/10 1:59 AM   1
5/30/10 1:59 AM   1
5/30/10 3:58 AM   2
5/30/10 3:58 AM   2
5/30/10 5:57 AM   2
5/30/10 6:57 AM   3
5/30/10 7:56 AM   3
5/30/10 7:56 AM   3
5/30/10 8:55 AM   3
5/30/10 11:54 AM  4

Итак, вы можете видеть, что когда я добираюсь до 3:58, он во 2-й группе, потому что это более 2 часов после 12:00. Однако 5:57 утра все еще во 2-й группе, хотя прошло более 4 часов после 12:00, потому что базовое время 2-й группы - 3:58, а не 2:00.

Я попытался создать столбец группировки с помощью функции разделения, подобной этой:

FLOOR(DATEDIFF(SECOND, t.BaseCreateDate, t.CreateDate) / t.DedupWindow)

Где BaseCreateDate - самая ранняя дата в моем наборе, CreateDate - данные, которые я перечислил, а DedupWindow - 2 часа. Однако, это дает мне фиксированные 2-часовые окна, и я не могу найти математику, которая сбрасывает базу по мере необходимости через данные.

У меня это работает в курсоре, но по нескольким причинам я хотел бы получить его на основе рабочего набора.

Ответы [ 2 ]

1 голос
/ 05 июня 2010

противно но работает http://cloudexchange.cloudapp.net/stackoverflow/q/2281

Агрегаты не допускаются в рекурсивной части CTE.

DECLARE @t AS TABLE (dt datetime) ;
INSERT  INTO @t
VALUES  ('5/30/10 12:00 AM')
INSERT  INTO @t
VALUES  ('5/30/10 12:01 AM')
INSERT  INTO @t
VALUES  ('5/30/10 1:59 AM')
INSERT  INTO @t
VALUES  ('5/30/10 1:59 AM') 
INSERT  INTO @t
VALUES  ('5/30/10 3:58 AM') 
INSERT  INTO @t
VALUES  ('5/30/10 3:58 AM') 
INSERT  INTO @t
VALUES  ('5/30/10 5:57 AM') 
INSERT  INTO @t
VALUES  ('5/30/10 6:57 AM') 
INSERT  INTO @t
VALUES  ('5/30/10 7:56 AM') 
INSERT  INTO @t
VALUES  ('5/30/10 7:56 AM')
INSERT  INTO @t
VALUES  ('5/30/10 8:55 AM')
INSERT  INTO @t
VALUES  ('5/30/10 11:54 AM') ;
WITH    CTE
          AS (
              SELECT    dt
                       ,1 AS bucket
              FROM      @t
              WHERE     dt = (
                              SELECT    MIN(dt)
                              FROM      @t
                             )
              UNION ALL
              SELECT    t.dt -- Cannot use aggregates here
                       ,CTE.bucket + 1 AS bucket
              FROM      CTE
              INNER JOIN @t AS t
                        ON t.dt >= DATEADD(HOUR, 2, CTE.dt)
             ),
        X AS (
              SELECT    dt
                       ,bucket
                       ,ROW_NUMBER() OVER (PARTITION BY BUCKET ORDER BY dt) AS bucket_start
              FROM      CTE
             ),
        Y AS (
              SELECT    *
              FROM      X
              WHERE     bucket_start = 1
             )
    SELECT  t.*
           ,(
             SELECT MAX(bucket)
             FROM   Y
             WHERE  Y.dt <= t.dt
            ) AS bucket
    FROM    @t AS t
0 голосов
/ 05 июня 2010

Редактировать: Вот довольно нелепое решение, которое, похоже, возвращает правильные результаты.

http://cloudexchange.cloudapp.net/stackoverflow/q/2282

 WITH DATE AS
(
SELECT '20100530 00:00:00.000'  AS CreateDate UNION ALL
SELECT '20100530 00:01:00.000' UNION ALL
SELECT '20100530 01:59:00.000' UNION ALL
SELECT '20100530 01:59:00.000' UNION ALL
SELECT '20100530 03:58:00.000' UNION ALL
SELECT '20100530 03:58:00.000' UNION ALL
SELECT '20100530 05:57:00.000' UNION ALL
SELECT '20100530 06:57:00.000' UNION ALL
SELECT '20100530 07:56:00.000' UNION ALL
SELECT '20100530 07:56:00.000' UNION ALL
SELECT '20100530 08:55:00.000' UNION ALL
SELECT '20100530 11:54:00.000'
),PossibleBuckets As
(
SELECT     earlier.CreateDate, MIN(later.CreateDate) AS NextBucket
FROM         Date AS earlier INNER JOIN
                      Date AS later ON later.CreateDate > earlier.CreateDate 
and later.CreateDate > DATEADD(hour, 2, earlier.CreateDate)  
GROUP BY earlier.CreateDate
),
dates AS (
    SELECT   TOP(1)  CreateDate, NextBucket, 1 AS rank
    FROM         PossibleBuckets
    ORDER BY CreateDate
  UNION ALL
  SELECT   PB.CreateDate, PB.NextBucket, Rank + 1 AS Rank
    FROM   PossibleBuckets PB
    JOIN dates on dates.NextBucket = PB.CreateDate
)
SELECT d.CreateDate, COALESCE(x.Rank, (SELECT MAX(Rank)+1 FROM dates), 1) AS Rank
  FROM date d left join dates x on d.CreateDate >= x.CreateDate AND d.CreateDate < x.NextBucket
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...