2015-03-13 4 views
0

У меня есть таблица транзакций со следующей структурой:Выбор записей с максимальным значением в группе

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]) 

, но это не дает мне никаких транзакций, в которых статус находится в состоянии ожидания (у них нет порядковых номеров). Как я могу исправить этот запрос?

+0

Что это за rdbms? –

+0

@TimSchmelter SQL Server 2012 – Otaia

ответ

1

Если это 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.

+0

Спасибо, это сработало! – Otaia

0

Попробуйте так, чтобы получить максимальное SequenceNumber

CASE WHEN MAX(SequenceNumber IS NULL) = 0 THEN MAX(SequenceNumber) ELSE NULL END AS SequenceNumber 
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; 
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 

Full Demo:

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 
0

omething так:

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 
Смежные вопросы