将SQL行分组到事务中,然后计算持续时间

时间:2014-04-07 20:06:50

标签: sql sql-server

我的表格结构如下。我想知道是否可以通过TransactionID压缩每个事务,从第一行和最后一行拉取值,然后最终计算事务的持续时间。

例如下面,我想拉RecordID和CustomerID。然后别名一个名为startingStatus的新列,该列将从第一行“提交”。我将别名第二列名为endingStatus,该列将是最后一行的“Success”。然后我需要以相同的方式获取时间戳,创建startingTime和endingTime。最后一列是开始和结束之间的差异。

RecordID    TransactionID   CustomerID  Status          TimeStamp
1                   12          10      Submitted       04/07/2014 14:32:23
2                   12          10      Queued          04/07/2014 14:32:24
3                   12          10      Processing      04/08/2014 14:32:26
4                   12          10      Error           04/09/2014 14:32:27
5                   12          10      Resubmitted     04/10/2014 15:12:29
6                   12          10      Queued          04/11/2014 15:12:31
7                   12          10      Processing      04/12/2014 15:12:34
8                   12          10      Success         04/13/2014 15:12:47

我一直试图通过TransactionID进行分组并使用MIN和MAX,但我还没有让它工作。

我将如何做这样的事情?

2 个答案:

答案 0 :(得分:1)

尝试一下:

SELECT 
    CustomerID, 
    TransactionID, 
    Min([TimeStamp]) as StartTime, 
    Max([TimeStamp]) as EndTime,
    DATEDIFF(MINUTE,Min([TimeStamp]),Max([TimeStamp])) as TransactionTime
FROM YourTable
GROUP BY CustomerID, TransactionID
ORDER BY CustomerID, TransactionID

答案 1 :(得分:1)

我会使用窗口函数来检索组的第一个和最后一个记录。

这将适用于SQL Server 2005及更高版本,方法是使用ROW_NUMBER()窗口函数,然后使用MAX / CASE WHEN方法旋转结果:

SELECT 
    [TransactionID], 
    [CustomerID], 
    MAX(CASE WHEN [rn_asc] = 1 THEN [Status] ELSE NULL END) [startingStatus], 
    MAX(CASE WHEN [rn_desc] = 1 THEN [Status] ELSE NULL END) [endingStatus], 
    MAX(CASE WHEN [rn_asc] = 1 THEN [TimeStamp] ELSE NULL END) [startingTimeStamp], 
    MAX(CASE WHEN [rn_desc] = 1 THEN [TimeStamp] ELSE NULL END) [endingTimeStamp],
    DATEDIFF(
        SECOND,
        MAX(CASE WHEN [rn_asc] = 1 THEN [TimeStamp] ELSE NULL END),
        MAX(CASE WHEN [rn_desc] = 1 THEN [TimeStamp] ELSE NULL END) 
    ) [duration]
FROM  
    ( 
        SELECT 
            [TransactionID], 
            [CustomerID], 
            ROW_NUMBER() OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] ASC) [rn_asc], 
            ROW_NUMBER() OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] DESC) [rn_desc], 
            [Status], 
            [Timestamp] 
        FROM [tbl]
    ) A 
GROUP BY  
    [TransactionID], 
    [CustomerID] 

SQL Server 2012引入了FIRST_VALUE函数,因此如果您运行的是该版本,则可以考虑此查询

SELECT DISTINCT
    [TransactionID], 
    [CustomerID], 
    FIRST_VALUE([Status]) OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] ASC) [startingStatus], 
    FIRST_VALUE([Status]) OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] DESC) [endingStatus],
    FIRST_VALUE([TimeStamp]) OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] ASC) [startingTimeStamp], 
    FIRST_VALUE([TimeStamp]) OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] DESC) [endingTimeStamp],
    DATEDIFF(
        SECOND,
        FIRST_VALUE([TimeStamp]) OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] ASC),
        FIRST_VALUE([TimeStamp]) OVER (PARTITION BY [TransactionID], [CustomerID] ORDER BY [RecordID] DESC)
    ) [duration]
FROM [tbl]