【问题标题】:Joining tables based on a datetime, but the datetime value can vary within 5 minutes基于日期时间连接表,但日期时间值可以在 5 分钟内变化
【发布时间】:2011-12-12 17:00:07
【问题描述】:

我在这里处理一些设计不佳的表格,改变结构或多或少是不可能的。话虽如此,这是我的问题。

我需要在 TableA.Date 上加入 TableB.Date,间隔约 5 分钟。换句话说,连接不能依赖完美匹配。

因此,如果 TableA 中的日期为 2011-12-01 10:00:00.000,则连接将匹配 TableB 中日期为 2011-12-01 10:03:00.0002011-12-01 09:59:00.0002011-12-01 10:04:35.000 的记录

我想出了一个小技巧,通过将 datetime 转换为 smalldatetime 来允许大约 1 分钟的差异,这会从 datetime 值中减去秒和毫秒。它工作得很好,但我需要比这更大的余量。

LEFT JOIN TableB ON CAST(TableA.SomeDate AS smalldatetime) = CAST(TableB.SomeDate AS smalldatetime)

TableB 中的日期列是两个表中数据之间的唯一链接,因此我无法在 WHERE 子句中过滤结果。我意识到这可能会产生一些不准确的结果,但由于数据的存储方式和时间,我不应该遇到任何问题。

有什么建议吗?

【问题讨论】:

  • 通过强制转换为 smalldatetime 进行截断甚至不能满足您的要求。相差一毫秒但落入不同分钟的时间将不匹配。您可以将表添加到现有数据库,例如创建一个表,将现有表中的日期/时间扩展到 5 分钟范围并编制索引?
  • 这样做的问题是您必须更严格地定义 5 分钟边距。如果 tableA 上的 2 个结果彼此相差 5 分钟之内怎么办?他们是否都加入了 tableB 上的同一条记录?然后你会得到重复的记录。您可能想要做的是将您的日期时间 bin 放入 5 分钟的桶中,但这种刚性可能不适合目的。如果您真正想做的是模糊数据分析,那么 SQL 可能是错误的语言选择。

标签: sql-server sql-server-2005 sql-server-2008 tsql


【解决方案1】:

尝试DATEDIFF 查找少于 300 秒的时间(分钟边界为零秒,这将给出不正确的结果)。为了更准确,请使用毫秒

TableA
LEFT JOIN 
TableB ON ABS(DATEDIFF(second, TableA.SomeDate, TableB.SomeDate)) < 300

【讨论】:

  • 这是个好主意,但不幸的是它需要很长时间才能运行。在我取消之前,查询运行了超过一分钟。使用普通连接大约需要 3 秒。
  • 添加自某个时期(例如 2000 年 1 月 1 日)以来的秒数计算列,并比较这些可以作为索引的计算列。如果 TableB 日期总是在 TableA 之后,那么它当然可以进一步简化
【解决方案2】:

这样做的问题是,您必须更严格地定义 5 分钟的边距才能使 SQL 正常工作。如果你想变得更模糊,那么 SQL 是错误的语言。

如果 tableA 上的 2 个结果彼此相差 5 分钟之内怎么办?他们是否都加入了 tableB 上的同一条记录?然后你会得到重复的记录。

您想要做的是 bin 使用向下/向上舍入计划将您的日期时间放入 5 分钟的存储桶(或您选择的任何东西)中。预先制作的查找表始终是一种快速执行的解决方案,该表将包含每天每分钟的索引列和您同意的 5 分钟存储桶的另一列。该中间表可用于将 tableA 连接到 tableB。

即LookupTable(请原谅格式!)

查找时间 __________ 存储桶时间

2013-01-01 14:56 _____ 2013-01-01 14:55

2013-01-01 14:57_____ 2013-01-01 14:55

2013-01-01 14:58_____ 2013-01-01 15:00

2013-01-01 14:59_____ 2013-01-01 15:00

您可以将 tableA 日期加入到上面的 LookupTime。 您将单独连接到 tableB 的 LookupTime 表的第二个副本, 然后在 BucketTime 字段上将查找表的两个副本相互连接。

棘手的部分是就您将使用的四舍五入达成一致。我推荐“舍入到偶数”,它可以消除舍入数字 1-4 向下和 5-9 向上的舍入偏差。

【讨论】:

    【解决方案3】:

    加入格式化日期。对它们进行格式化,以便它们四舍五入到最接近的 5 分钟或四舍五入到相关的时间跨度。它可能需要一个用户定义的函数。

    【讨论】:

    • 我担心我可能不得不这样做。我希望有人能想出一个技巧来解决这个问题,就像 gbn 的回应一样。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 2017-05-17
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多