基于最近时间戳连接两个表的 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 小时内看到过”?