选择组中具有最大值的记录

时间:2015-03-13 16:29:41

标签: sql sql-server sql-server-2012

我有一个具有以下结构的事务表:

select t.[GUID], t.[ID], ts.Description "Status", t.Payee, t.Amount, t.SequenceNumber
  from [Transaction] t
 inner join TransactionStatus ts on t.StatusID = ts.ID

GUID                                 | ID | Status  | Payee | Amount | SequenceNumber
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 1  | Posted  | Amy   | 500.00 | 1
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 2  | Voided  | Amy   | 500.00 | 2
1F7D880C-E7C0-E411-B8F6-004056AB77C2 | 3  | Posted  | Bob   |  70.00 | 1
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 4  | Posted  | Amy   | 512.50 | 3
1F7D880C-E7C0-E411-B8F6-004056AB77C2 | 5  | Posted  | Bob   |  66.00 | 2
F2CC0B03-76C7-E411-A48D-004056AB787C | 6  | Pending | Carol | 240.00 | NULL

我正在尝试构建一个查询来按GUID对记录进行分组,并选择具有最大SequenceNumber的单个记录(如果它不是NULL):

GUID                                 | ID | Status  | Payee | Amount | SequenceNumber
AF732CF5-E6C0-E411-B8F6-004056AB77C2 | 4  | Posted  | Amy   | 512.50 | 3
1F7D880C-E7C0-E411-B8F6-004056AB77C2 | 5  | Posted  | Bob   | 66.00  | 2
F2CC0B03-76C7-E411-A48D-004056AB787C | 6  | Pending | Carol | 240.00 | NULL

我尝试添加此行:

where SequenceNumber = (select MAX(SequenceNumber) from [Transaction] t2 where t.[GUID] = t2.[GUID])

但这并没有让我得到状态为待定的任何交易(他们没有序列号)。如何解决此问题?

5 个答案:

答案 0 :(得分:1)

如果是SQL-Server,您可以使用CTE + ROW_NUMBER

WITH CTE AS
(
    select t.[GUID], t.[ID], ts.Description "Status", t.Payee, t.Amount, t.SequenceNumber,
           rn = row_number() over (partition by  t.[GUID] Order By t.SequenceNumber DESC)
    from [Transaction] t
    inner join TransactionStatus ts on t.StatusID = ts.ID
)
SELECT GUID, ID, Status, Payee, Amount, SequenceNumber
FROM CTE
WHERE rn = 1

这将包括SequenceNumber为空的行。如果您希望具有最大SequenceNumber的所有行(如果是关系)使用DENSE_RANK而不是ROW_NUMBER

答案 1 :(得分:1)

您可以在子查询和MAX(ID)中计算[GUID]及其相关JOIN以获得所需结果:

示例子查询:

SELECT  [GUID] ,
        MAX(ID) MaxId
FROM    Transaction
GROUP BY [GUID]

会产生:

GUID                                    MaxId
1F7D880C-E7C0-E411-B8F6-004056AB77C2    5
AF732CF5-E6C0-E411-B8F6-004056AB77C2    4
F2CC0B03-76C7-E411-A48D-004056AB787C    6

完整演示:

CREATE TABLE #Transaction
    (
      [GUID] VARCHAR(36) ,
      [ID] INT ,
      [Status] VARCHAR(7) ,
      [Payee] VARCHAR(5) ,
      [Amount] INT ,
      [SequenceNumber] VARCHAR(4)
    );

INSERT  INTO #Transaction
        ( [GUID], [ID], [Status], [Payee], [Amount], [SequenceNumber] )
VALUES  ( 'AF732CF5-E6C0-E411-B8F6-004056AB77C2', 1, 'Posted', 'Amy', 500.00,
          '1' ),
        ( 'AF732CF5-E6C0-E411-B8F6-004056AB77C2', 2, 'Voided', 'Amy', 500.00,
          '2' ),
        ( '1F7D880C-E7C0-E411-B8F6-004056AB77C2', 3, 'Posted', 'Bob', 70.00,
          '1' ),
        ( 'AF732CF5-E6C0-E411-B8F6-004056AB77C2', 4, 'Posted', 'Amy', 512.50,
          '3' ),
        ( '1F7D880C-E7C0-E411-B8F6-004056AB77C2', 5, 'Posted', 'Bob', 66.00,
          '2' ),
        ( 'F2CC0B03-76C7-E411-A48D-004056AB787C', 6, 'Pending', 'Carol',
          240.00, NULL );

SELECT  #Transaction.*
FROM    #Transaction
        INNER JOIN ( SELECT [GUID] ,
                            MAX(ID) MaxId
                     FROM   #Transaction
                     GROUP BY [GUID]
                   ) t ON t.[GUID] = #Transaction.[GUID]
                          AND t.MaxId = #Transaction.ID
ORDER BY ID

答案 2 :(得分:0)

尝试这种方式获得最大SequenceNumber

CASE WHEN MAX(SequenceNumber IS NULL) = 0 THEN MAX(SequenceNumber) ELSE NULL END AS SequenceNumber

答案 3 :(得分:0)

我不知道SQL Server是否具有窗口函数,因此您可以更干净地执行此操作,但这是一个普通的SQL解决方案:

select    highest.[GUID],
          highest.[ID],
          ts.Description "Status",
          highest.Payee,
          highest.Amount,
          highest.SequenceNumber
from      [Transaction] highest
join      TransactionStatus ts
on        ts.ID                 = highest.ID
left join [Transaction] higher
on        higher.[GUID]         = highest.[GUID]
and       higher.SequenceNumber > highest.SequenceNumber
where     higher.[GUID]        is null;

答案 4 :(得分:0)

类似的东西:

SELECT * FROM
(
  select 
        t.[GUID], t.[ID], ts.Description "Status", t.Payee, t.Amount, 
        ROW_NUMBER() OVER PARTITION BY (t.[GUID]
    ORDER BY t.SequenceNumber DESC) AS rownum
              from [Transaction] t
             inner join TransactionStatus ts on t.StatusID = ts.ID
)vals where vals.rownum = 1