将三个具有唯一时间戳的数据库表匹配的最佳方法是啥?
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
【讨论】:
以上是关于将三个具有唯一时间戳的数据库表匹配的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章