Объединить несколько соседних дат с SQL - PullRequest
0 голосов
/ 23 апреля 2019

Я пытаюсь объединить несколько смежных дат, чтобы получить одну запись.

Например, у меня есть следующие пропуски для одного сотрудника:

02-Mai-17   01-Apr-18
02-Apr-18   01-Apr-19
02-Apr-19   01-Apr-20
02-Apr-20   30-Aug-20

Результат должен быть: 02-Май-17 30 августа-20

Я пробовал с Объединить последовательные диапазоны дат , чтобы объединить соседние даты, но, насколько я понимаю, это работает только для одной дополнительной соседней даты.

Я загрузил пример базы данных в https://www.file -upload.net / download-13581528 / Database1.accdb.html

SELECT IT2001.Id, IT2001.Kind, IT2001.Start, IT2001.End, 'Typ1'
FROM IT2001 LEFT JOIN IT2001 AS IT2001_1 ON (IT2001.Id = IT2001_1.Id) AND (IT2001.Kind = IT2001_1.Kind) AND (IT2001.Start-1=IT2001_1.End)
WHERE IT2001_1.Id IS NULL 
UNION ALL
SELECT IT2001.Id, IT2001.Kind, IT2001.Start, IT2001_1.End, 'Typ2'
FROM IT2001 INNER JOIN IT2001 AS IT2001_1 ON (IT2001.Id = IT2001_1.Id) AND (IT2001.Kind = IT2001_1.Kind) AND (IT2001_1.Start-1=IT2001.End)

, а затем:

SELECT Query1.Id, Query1.Kind, MIN(Query1.Start), Max(Query1.End)
FROM Query1
GROUP BY Query1.Id, Query1.Kind, Query1.Start

Я получаю 3 строки вместо одной:

02-Mai-17   01-Apr-19
02-Apr-18   01-Apr-20
02-Apr-19   30-Aug-20

Как получить одну строку или как удалить ненужные записи?

Ответы [ 2 ]

0 голосов
/ 30 апреля 2019

Полагаю, я решил это с помощью VBA и хотел бы пригласить вас прокомментировать или улучшить его:

Sub mergeDates()
    Set db = CurrentDb

    i = 1
    Do While i > 0
        SQL = "UPDATE (IT2001 LEFT JOIN IT2001 AS IT2001_1 ON (IT2001.Start-1 = IT2001_1.End) AND (IT2001.Id = IT2001_1.Id) AND (IT2001.Kind = IT2001_1.Kind)) LEFT JOIN IT2001 AS IT2001_2 ON (IT2001.End = IT2001_2.Start-1) AND (IT2001.Kind = IT2001_2.Kind) AND (IT2001.Id = IT2001_2.Id)" & _
            " Set IT2001.End = IT2001_2.End, IT2001.combined=NZ(IT2001.combined,0)+1, IT2001_2.Delete = true" & _
            " Where IT2001_1.Start Is Null AND IT2001_2.End IS NOT NULL"
        db.Execute SQL

        delSQL = "DELETE * FROM IT2001 WHERE delete = true"
        db.Execute delSQL
        i = db.RecordsAffected

        j = j + 1
        If (j >= 10) Then
            i = 0
        End If
    Loop

End Sub

  • Я проверяю, является ли текущая записьпервый в строке (IT2001_1.Start Is Null) и
  • - если есть дата прилагательного (IT2001_2.End IS NOT NULL).
  • Если оба значения true, перенесите вторую конечную дату впервая конечная дата (IT2001.End = IT2001_2.End) и отметьте вторую удаляемую запись (IT2001_2.Delete = true)
  • Я удаляю все записи, где delete - true (DELETE * FROM IT2001, WHERE delete = true)

Я помещаю это в цикл while для слияния, пока не получу 0 затронутых записей (i = db.RecordsAffered)

У кого-нибудь есть предложения или улучшения?

0 голосов
/ 24 апреля 2019

Поскольку все диапазоны не оставляют разрыва, это будет делать:

SELECT 
    Min(IT2001.Start) AS FirstDate, 
    Max(IT2001.End) AS LastDate
FROM 
    IT2001;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...