基于最近时间戳连接两个表的 SQL 查询

Posted

技术标签:

【中文标题】基于最近时间戳连接两个表的 SQL 查询【英文标题】:SQL Query to Join Two Tables Based On Closest Timestamp 【发布时间】:2013-03-31 15:30:15 【问题描述】:

我需要从 dbo.transaction(所有用户的交易 - 每个用户的多个交易)中检索时间戳最接近 dbo.bal 中时间的记录(每个用户的当前余额详细信息 - 只有一个每个用户的记录)

即,结果记录应等于 dbo.bal 中的记录数

在这里我尝试了下面的查询,我只得到少于 dbo.bal 时间的记录。但是有些记录的时间戳大于和最接近 dbo.bal.time

SELECT dbo.bal.uid,
       dbo.bal.userId,
       dbo.bal.balance,
       dbo.bal.time,
  (SELECT TOP 1 transactionBal
   FROM dbo.transaction
   WHERE TIMESTAMP <= dbo.bal.time
   ORDER BY TIMESTAMP DESC) AS newBal
FROM dbo.bal
WHERE dbo.bal.time IS NOT NULL
ORDER BY dbo.bal.time DESC

这是我的表结构,

dbo.transaction
---------------

| uid| userId   | description| timestamp               | credit | transactionBal
-------------------------------------------------------------------------
| 1  | 101      | buy credit1| 2012-01-25 03:23:31.624 | 100    | 500
| 2  | 102      | buy credit5| 2012-01-18 03:13:12.657 | 500    | 700
| 3  | 103      | buy credit3| 2012-01-15 02:16:34.667 | 300    | 300
| 4  | 101      | buy credit2| 2012-01-13 05:34:45.637 | 200    | 300
| 5  | 101      | buy credit1| 2012-01-12 07:45:21.457 | 100    | 100
| 6  | 102      | buy credit2| 2012-01-01 08:18:34.677 | 200    | 200

dbo.bal
-------

| uid| userId   | balance | time                    |
-----------------------------------------------------
| 1  | 101      | 500     | 2012-01-13 05:34:45.645 |
| 2  | 102      | 700     | 2012-01-01 08:18:34.685 |
| 3  | 103      | 300     | 2012-01-15 02:16:34.672 |

结果应该是这样的,

| Id | userId   | balance | time                    | credit | transactionBal 
-----------------------------------------------------------------------------
| 1  | 101      | 500     | 2012-01-13 05:34:45.645 | 200    | 300
| 2  | 102      | 700     | 2012-01-01 08:18:34.685 | 200    | 200
| 3  | 103      | 300     | 2012-01-15 02:16:34.672 | 300    | 300

请帮助我..任何帮助都必须感谢...谢谢

【问题讨论】:

还提到了上述两个表中所需的结果集。 【参考方案1】:

如果您发布表结构会很有帮助,但是...

    我认为您的内部查询需要一个连接条件。 (这实际上不是你的问题)

    内部查询中的ORDER BY 子句可能是ABS(TIMESTAMP - DB0.BAL.TIME)。这应该会给你两者之间的最小差异。

这有帮助吗?

基于以下 Sql Fiddle http://sqlfiddle.com/#!3/7a900/15 我想出了...

SELECT 
  bal.uid, 
  bal.userId, 
  bal.balance, 
  bal.time,
  trn.timestamp,
  trn.description,
  datediff(ms, bal.time, trn.timestamp)
FROM 
  money_balances bal
  JOIN money_transaction trn on
    trn.userid = bal.userid and
    trn.uid =
    (
      select top 1 uid
      from money_transaction trn2
      where trn2.userid = trn.userid
      order by abs(datediff(ms, bal.time, trn2.timestamp))
    )
WHERE 
  bal.time IS NOT NULL
ORDER BY 
  bal.time DESC

我不能保证它的性能,因为我对你的数据一无所知,但我相信它有效。

我已经简化了我的答案 - 我相信你需要的是

SELECT 
  bal.uid as baluid,   
  (
      select top 1 uid 
      from money_transaction trn2
      where trn2.userid = bal.userid
      order by abs(datediff(ms, bal.time, trn2.timestamp))
  ) as tranuid
FROM 
  money_balances bal

然后您可以从中派生出您需要的所有数据集。 例如:

with matched_credits as
(
SELECT 
  bal.uid as baluid,   
  (
      select top 1 uid 
      from money_transaction trn2
      where trn2.userid = bal.userid
      order by abs(datediff(ms, bal.time, trn2.timestamp))
  ) as tranuid
FROM 
  money_balances bal 
)
select 
  *
from 
  matched_credits mc
  join money_balances mb on
    mb.uid = mc.baluid
  join money_transaction trn on
    trn.uid = mc.tranuid

【讨论】:

你能根据第一个建议帮助我吗..?这可行吗?如果您为查询提供内部连接会更有帮助。 我们必须查看您的表格和一些示例数据,但绝对有一个解决方案 - 您所要求的并非不可能。 我已经用表格结构更新了我的问题..你能检查一下吗? 我已经检查过这里,但是,1.我得到了这个错误“datediff 函数导致溢出。分隔两个日期/时间实例的 dateparts 的数量太大。尝试使用带有 less 的 datediff精确的日期部分。” 2. 此外,您似乎在这里考虑 datediff 的 'ms' 部分。它可能是 hours 、 minits 等(唯一条件是接近时间的时间戳) 1.我认为那是因为我不得不猜测您的数据类型。看看下面 Mark 的帖子 - 转换为浮动可能是最好的。【参考方案2】:

试试:

SELECT dbo.bal.uid,
       dbo.bal.userId,
       dbo.bal.balance,
       dbo.bal.time,
  (SELECT TOP 1 transactionBal
   FROM dbo.transaction
   ORDER BY abs(datediff(ms, dbo.bal.time, TIMESTAMP))) AS newBal
FROM dbo.bal
WHERE dbo.bal.time IS NOT NULL
ORDER BY dbo.bal.time DESC

【讨论】:

以上是关于基于最近时间戳连接两个表的 SQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询:如果给定两个 DateTime 时间戳,如何确定“在 N 小时内看到过”?

Spark SQL 查询以获取在 AWS S3 中存储为 CSV 的 Athena 表的最后更新时间戳

基于 MAX 时间戳的 SQL 内连接

如何编写SQL查询以基于时间戳从DB获取数据

跨表的 SQL VALUES 和 MAX

需要在 DB2 中使用基于时间戳的 group by 优化慢查询