【问题标题】:Merge several adjacent dates with SQL用 SQL 合并几个相邻的日期
【发布时间】:2019-04-23 20:17:50
【问题描述】:

我正在尝试合并几个相邻的日期以获得一个条目。

例如,我有以下一位员工缺勤:

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

结果应该是: 2017 年 5 月 2 日 20 年 8 月 30 日

我尝试使用 Combine consecutive date ranges 合并相邻日期,但它仅适用于我理解的另一个相邻日期。

我在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 行而不是 1 行:

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

如何获得一行或如何删除不需要的条目?

【问题讨论】:

  • 这在 MS Access 中真的很痛苦。你有其他数据库吗?你会碰巧有一个日历表或数字表吗?
  • 不幸的是我只能使用 MS Access,但我可以添加一个新的日历表。我可以使用日历表来查询新表应该包含哪些数据?
  • 尝试从您的 GROUP BY 子句中删除 Query1.Start
  • 是的,这行得通,但是如果日期之间出现间隔(至少 1 天)怎么办?

标签: sql ms-access


【解决方案1】:

由于所有范围组合起来没有间隙,因此可以这样做:

SELECT 
    Min(IT2001.Start) AS FirstDate, 
    Max(IT2001.End) AS LastDate
FROM 
    IT2001;

【讨论】:

  • 困难在于检查间隙。我出现了一个空白,日期无法合并。你有处理这个的想法吗?
  • 您的示例数据没有任何差距。这就是我们所拥有的 - 匹配:结果应该是:02-Mai-17 30-Aug-20
  • 你说得对,所描述的问题已经解决:-) 但是你永远不会得到哪些数据,我想我也会得到有差距的数据。这看起来要复杂得多,但是您知道如何解决这些情况吗?
  • 并非没有预期的结果。
【解决方案2】:

我想我用 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

结束子

  • 我检查当前条目是否是行中的第一个(IT2001_1.Start Is Null)并且
  • 是否有相邻日期(IT2001_2.End IS NOT NULL)。
  • 如果两者都为真,则将第二个结束日期接管到第一个结束日期 (IT2001.End = IT2001_2.End) 并标记要删除的第二个条目 (IT2001_2.Delete = true)
  • 我删除所有删除为 true 的条目(DELETE * FROM IT2001 WHERE delete = true)

我把它放在 while 循环中进行合并,直到我得到 0 条受影响的记录 (i = db.RecordsAffected)

有人有什么建议或改进吗?

【讨论】:

    猜你喜欢
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 2023-03-04
    • 2020-12-26
    相关资源
    最近更新 更多