将三个具有唯一时间戳的数据库表匹配的最佳方法是啥?

Posted

技术标签:

【中文标题】将三个具有唯一时间戳的数据库表匹配的最佳方法是啥?【英文标题】:What is the best way to match three DB tables with unique time stamps?将三个具有唯一时间戳的数据库表匹配的最佳方法是什么? 【发布时间】:2015-03-03 19:04:39 【问题描述】:

我有三个表格,它们全天从三个数据源接收新信息。

Table A     Table B     Table C
5, 8:00     J, 8:00     3, 8:00
6, 8:01     K, 8:02     8, 8:04
4, 8:03
9, 8:06

在一天结束的时候,我想按时间顺序处理数据,因为三个时间戳中的任何一个都发生了变化,因此我需要最近的三条信息。我想要的结果是:

Table A     Table B     Table C     *Data As of*
5, 8:00     J, 8:00     3, 8:00     *8:00*
6, 8:01     J, 8:00     3, 8:00     *8:01*
6, 8:01     K, 8:02     3, 8:00     *8:02*
4, 8:03     K, 8:02     3, 8:00     *8:03*
4, 8:03     K, 8:02     8, 8:04     *8:04*
9, 8:06     K, 8:02     8, 8:04     *8:06*

我目前正在将 3 个查询转储到 3 个数据表中。然后我通过取三个中最早的时间戳来一次遍历所有三个。这可行,但有点麻烦。一张表每天大约有 300 万条记录,一张有 200 条,一张只有几条。有时我一次处理 20 天的数据。对最佳方法的想法?

【问题讨论】:

您需要同时获得所有三个表的结果,还是每个表有一个查询可以? 您以某种方式将行复制到结果中?是什么决定了 A 中的 6 和 4 是两倍,或者 B 中的 K 是 4 倍? 哦,我想我明白了,你想要每分钟的结果,从每个表中获取最新的行,其中时间是参考时间或更小? @JamesZ 实际上是 3 个表中的每个唯一时间。请注意,8:05 不在表格或结果中。 我确实需要同时获得所有三个信息。该示例使用偶数秒,但考虑到表的大小,显然有毫秒精度的时间戳。 【参考方案1】:

这至少是一种方法。可能需要对性能进行一些分析,但这假设您创建了一个具有不同时间的表。如果在分钟级别(或桌面上的任何内容)还不够,您当然可以在运行此之前从每个表中“插入#time select distinct time ...”,但这可能是相当的也很重。

select distinct
  a.id as a_id,
  a.time as a_time,
  b.id as b_id,
  b.time as b_time,
  c.id as c_id,
  c.time as c_time
from
  time t

  outer apply (
    select top 1 id, time
    from tablea a
    where a.time <= t.time
    order by a.time desc
  ) a

  outer apply (
    select top 1 id, time
    from tableb b
    where b.time <= t.time
    order by b.time desc
  ) b

  outer apply (
    select top 1 id, time
    from tablec c
    where c.time <= t.time
    order by c.time desc
  ) c

order by 
  a_time, 
  b_time, 
  c_time

SQL 小提琴:http://sqlfiddle.com/#!3/de7ae/6

【讨论】:

【参考方案2】:

尝试下一个脚本(SQL2012+):

-- Step #1: it creates a table to store all distinct TS
CREATE TABLE #AllTS (TS DATETIME NOT NULL PRIMARY KEY) -- Change type of TS column with the proper data type

-- Step #2: it inserts distinct (UNION) TS values
INSERT  #AllTS
SELECT  TS
FROM (
    SELECT TS FROM dbo.A
    UNION SELECT TS FROM dbo.B
    UNION SELECT TS FROM dbo.C
) x(TS)

-- Step #3: for every source table use bellow query to generate requested resultset
SELECT  MAX(y.Col1)OVER(PARTITION BY GroupID) AS Col1,
        MAX(y.TS)OVER(PARTITION BY GroupID) AS TS
FROM (
    SELECT  a.Col1, a.TS, SUM(CASE WHEN a.TS IS NOT NULL THEN 1 ELSE 0 END) OVER(ORDER BY x.TS) AS GroupID
    FROM    #AllTS x LEFT JOIN dbo.A a ON x.TS = a.TS
) y

注意 1:您应该尝试使用在 TS 列上的每个源表上创建的索引来加速上述查询。示例:

CREATE INDEX IX_A_TS_#_Col1 ON dbo.A(TS) INCLUDE (Col1)

注意 2:此外,为了提高最后一个查询的性能,您可以测试不同的联合提示:

#AllTS x LEFT HASH JOIN dbo.A -- Could be useful  when source tables are "big"

#AllTS x MERGE JOIN dbo.A

Demo

【讨论】:

以上是关于将三个具有唯一时间戳的数据库表匹配的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

为银行交易生成 OrderId 的最佳方法是啥?

构建具有大量数据通信的系统的最佳方法是啥?

第一次将数据从其他来源插入应用程序表的最佳方法是啥?

在单个查询中从他们的 ID 获取相关数据的最佳方法是啥?

从字典列表创建 Pandas MultiIndex 的最佳方法是啥?

从时间戳图像对创建 HDF5 数据集的最佳方法是啥?