基于最近时间戳加入两个表的SQL查询

时间:2013-04-09 09:13:15

标签: sql sql-server sql-server-2008 join timestamp

我需要从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

请帮助我..任何帮助都必须得到赞赏...谢谢你

2 个答案:

答案 0 :(得分:2)

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

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

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

  3. 这有帮助吗?

    基于下面的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 :(得分:1)

尝试:

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