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

Selecting records with maximum value in group

我有一个交易 table 具有以下结构:

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 和 select 具有最大 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])

但这并没有让我得到任何状态为待处理的交易(它们没有序列号)。我该如何解决这个问题?

如果是 SQL-服务器,您可以使用 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

尝试这种方式以获得最大值SequenceNumber

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

我不知道 SQL 服务器是否有窗口功能,因此您可以更干净地执行此操作,但这里有一个普通的 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;

您可以计算 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

像这样:

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