【问题标题】:Query that recursively compare a record with the previous one递归比较一条记录与前一条记录的查询
【发布时间】:2014-08-20 13:13:11
【问题描述】:

我有下表示例

CREATE TABLE [dbo].[Transactions](
    [TransactionID] [int] IDENTITY(1,1) NOT NULL,
    [TransactionTypeID] [int] NOT NULL,
    [Counter] [int] NOT NULL,
    [GivenCounter] [int] NOT NULL,
    [ExecutionDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Transactions] PRIMARY KEY CLUSTERED ([TransactionID] ASC)

TransactionTypeID 字段标识交易类型:

  • 1 表示激活
  • 2 表示消耗
  • 3 表示取消

特别是type 3 是指取消之前的交易。因此,如果在取消之前已经执行的交易(以 ExecutionDate 而言)是type 2,则意味着取消消费,而如果之前的交易是type 1,则意味着取消是取消激活。

如何只查询含义为停用的交易(type 3 与之前的type 1)? 有人可以帮忙吗?

编辑:添加了一些示例数据以更好地解释

TransactionID   TransactionTypeID   Counter  GivenCounter    ExecutionDate  
--------------  -----------------   -------  ------------    -----------------------
138327              1               1          0             2014-07-20 07:14:08.000
134175              2               0          1             2014-07-21 12:39:12.000
137620              3               1          1             2014-07-22 20:19:06.000
134199              1               1          0             2014-07-23 10:09:52.000
132772              3               0          1             2014-07-24 08:18:23.000

在这个例子中,我的查询应该只提取一条记录 (TransactionID 132772),因为它取消了之前的交易,TransactionTypeID 等于 1

【问题讨论】:

  • 你怎么知道132772131199的取消?肯定有某个专栏将这两者联系在一起吗?
  • 没有。没有任何列将记录联系在一起。 TransactionTypeID = 3 的记录在执行日期方面与前一条记录相关。

标签: sql sql-server sql-server-2008-r2 common-table-expression recursive-query


【解决方案1】:

我会这样做:

SELECT a.transactionid 
FROM   (SELECT *, Row_number() OVER(ORDER BY ExecutionDate) AS Rownumber 
        FROM   transactions) a 
       JOIN (SELECT transactiontypeid, Row_number()  OVER( ORDER BY ExecutionDate) AS Rownumber 
             FROM   transactions) b 
         ON a.rownumber = b.rownumber + 1 
WHERE  a.transactiontypeid = 1 
       AND b.transactiontypeid = 3 

【讨论】:

  • 感谢您的回答,但我认为使用Row_number() 不能满足我的要求。唯一可以确定的是通过选择具有ExecutionDate less than current ExecutionDate的第一个可用事务来使用ExecutionDate 字段
  • 我认为如果您按 ExecutionDate 订购表格会起作用,请参阅我的编辑
  • 好的。让我做一些测试,我会尽快回复您
  • 这是完美的工作。我只颠倒了你的位置,因为第一个必须是 1 型,第二个必须是 3 型。我还编辑了你的答案。伟大的。非常感谢!
【解决方案2】:

我已经更新了我的答案,你可以试试这个吗?

SELECT *
FROM
(
SELECT 
DENSE_RANK() OVER (PARTITION BY (TransactionTypeID) ORDER BY (ExecutionDate)) AS 'RowNo',
TransactionID, TransactionTypeID, ExecutionDate
FROM dbo.Transactions2
WHERE TransactionTypeID = 3
 ) AS A
WHERE RowNo = 2;

【讨论】:

  • 感谢您的回答,但很遗憾我无法使用CounterGivenCounter 来选择数据。样本数据中的值更多。我只需要使用TransactionTypeIDExecutionDate
  • 这将为上面的testdata输出正确的行,但这只是巧合
  • 嘿 Lorenzo,你确定 TheJoe 的答案正常吗?我已经在样本数据上对其进行了测试,并且我还获得了也有激活和消费的取消的 transactionid !!!请仔细检查。
  • @Claudio:是的,克劳迪奥。我有一个包含超过 130K 记录的数据库,并且我知道我必须期待的结果。我已经针对不同的条件测试了该查询,它似乎对我来说非常有效。你有什么疑问?
  • TheJoelaut 的这行代码应该是这样的 ON a.rownumber = b.rownumber - 1 而不是 +1... 我在样本数据上对其进行了测试。 +1 还返回一些包含 idtype 1,2,3 的 transactionid,而不仅仅是那些 1,3
猜你喜欢
  • 1970-01-01
  • 2017-05-08
  • 2018-08-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多