Слияние записей на основе разницы во времени? - PullRequest
2 голосов
/ 03 августа 2011

У меня есть следующая таблица:

CREATE TABLE #TEMP (id int, name varchar(255), startdate datetime, enddate datetime)
INSERT INTO #TEMP VALUES(1, 'John', '2011-01-11 00:00:00.000','2011-01-11 00:01:10.000')
INSERT INTO #TEMP VALUES(2, 'John', '2011-01-11 00:00:20.000','2011-01-11 00:01:50.000')
INSERT INTO #TEMP VALUES(3, 'John', '2011-01-11 00:01:40.000','2011-01-11 00:01:50.000')
INSERT INTO #TEMP VALUES(4, 'Adam', '2011-01-11 00:00:40.000','2011-01-11 00:01:20.000')
INSERT INTO #TEMP VALUES(5, 'Adam', '2011-01-11 00:00:10.000','2011-01-11 00:01:30.000')

SELECT * FROM #TEMP

DROP TABLE #TEMP

Я пытаюсь объединить все записи с одинаковыми именами в диапазоне 60 секунд друг с другом, чтобы получить следующее:

John 2011-01-11 00:00:00.000 2011-01-11 00:01:10.000
John 2011-01-11 00:01:40.000 2011-01-11 00:01:50.000
Adam 2011-01-11 00:00:10.000 2011-01-11 00:01:20.000

Какие-либо предложения о том, как сделать это на столе с записями около 50К?В настоящее время мне удалось добраться до этого:

SELECT * FROM #TEMP

CREATE TABLE #Merge(id1 int, id2 int)

INSERT INTO #Merge
SELECT id, uuid
FROM
(
    SELECT t.id, u.uuid, t.name, t.startdate, t.enddate, u.ustartdate, u.uenddate,
           (CASE WHEN (DATEDIFF(second, t.startdate, u.ustartdate) <= 60 AND DATEDIFF(second, t.startdate, u.ustartdate) >= 0) then 1 else 0 END) Flag
    FROM #Temp t 
    INNER JOIN
    (SELECT id AS uuid, name, startdate AS ustartdate, enddate AS uenddate
    FROM #Temp) u 
    ON t.name = u.name AND t.startdate != u.ustartdate AND t.id != u.uuid
) w
WHERE Flag = 1

SELECT * FROM #Merge

-- Insert non-mergable records
CREATE TABLE #TEMP2 (id int, name varchar(255), membergroup varchar(255), startdate datetime, enddate datetime)
INSERT INTO #TEMP2
SELECT * FROM #TEMP
WHERE id NOT IN (SELECT id1 FROM #Merge UNION SELECT id2 FROM #Merge)

SELECT * FROM #TEMP2

Конечно, я не уверен, как действовать дальше.Таблица #Merge дает мне строки, которые должны быть объединены.Что я сделал, так это сначала вставил не слитые строки в # Temp2. ​​

РЕДАКТИРОВАТЬ:

Обновлен набор строк, на всякий случай:

INSERT INTO #TEMP VALUES(1, 'John', 'A', '2011-01-11 00:00:00.000','2011-01-11 00:01:10.000')
INSERT INTO #TEMP VALUES(2, 'John', 'A', '2011-01-11 00:00:01.000','2011-01-11 00:01:10.000')
INSERT INTO #TEMP VALUES(3, 'John', 'B', '2011-01-11 00:00:20.000','2011-01-11 00:01:50.000')
INSERT INTO #TEMP VALUES(4, 'John', 'C', '2011-01-11 00:01:40.000','2011-01-11 00:01:50.000')
INSERT INTO #TEMP VALUES(5, 'John', 'C', '2011-01-11 00:01:50.000','2011-01-11 00:02:20.000')
INSERT INTO #TEMP VALUES(6, 'Adam', 'A', '2011-01-11 00:00:40.000','2011-01-11 00:01:20.000')
INSERT INTO #TEMP VALUES(7, 'Adam', 'B', '2011-01-11 00:00:10.000','2011-01-11 00:01:30.000')
INSERT INTO #TEMP VALUES(8, 'Adam', 'B', '2011-01-11 00:03:10.000','2011-01-11 00:04:30.000')

Ответы [ 2 ]

2 голосов
/ 03 августа 2011

Приведенный ниже код управления отображает как объединенные строки (строки 1-2,4-5), так и уникальные строки (строка 3)

SELECT DISTINCT a.id,a.name,a.startdate,a.enddate
FROM temp a
  LEFT JOIN temp b ON a.name = b.name AND a.id < b.id AND DATEDIFF(s,a.startdate,b.startdate)<=60
  LEFT JOIN temp c ON c.name = a.name AND c.id < a.id AND DATEDIFF(s,c.startdate,a.startdate)<=60
WHERE (b.id IS NOT NULL OR c.id IS NULL) AND a.id <= COALESCE(c.id,a.id)

enter image description here

1 голос
/ 03 августа 2011

Учитывая, что вы не сказали, как использовать 60-секундный интервал, и ваш пример кода показал только сравнение начальной даты, здесь вы идете

SELECT
    *
FROM
    #Temp t1
    CROSS APPLY
    (SELECT TOP 1*
    FROM #Temp t2
    WHERE t1.name = t2.name AND DATEDIFF(second, t1.startdate, t2.startdate) < 60 AND t1.id < t2.id
    ORDER BY id DESC
    ) t2x

На основании только начальной даты пары строк 1/2 и 4/5 попадают в выходной файл. Строка 3 - нет, поэтому вам придется объяснить, почему вы ее добавили.

То есть идентификатор строки = 3 равен , а не в течение 60 секунд после строки 1 или 2 на основе начальной даты. Так что не должно быть в выводе.

Предполагается, что id и startdate увеличиваются.

Изменить, после чата:

SELECT
    *
FROM
    #Temp t1
    CROSS APPLY
    (SELECT TOP 1 *
    FROM #Temp t2
    WHERE t1.name = t2.name AND DATEDIFF(second, t1.startdate, t2.startdate) < 60 AND t1.id < t2.id
    ORDER BY t2.id DESC
    ) t2x
UNION ALL
SELECT
    t1.*, t1.*
FROM
    #Temp t1
WHERE NOT EXISTS
(
    SELECT
        t1ZZ.id, t2xZZ.id
    FROM
        #Temp t1ZZ
        CROSS APPLY
        (SELECT TOP 1 *
        FROM #Temp t2ZZ
        WHERE t1ZZ.name = t2ZZ.name AND DATEDIFF(second, t1ZZ.startdate, t2ZZ.startdate) < 60 AND t1ZZ.id < t2ZZ.id
        ORDER BY t2ZZ.id DESC
        ) t2xZZ
     WHERE
        t1.id IN (t1ZZ.id, t2xZZ.id)
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...