Retornando um conjunto de resultados com várias linhas com base na data máxima

16

Eu tenho uma tabela filho que é algo como isto:

[Tabela de data de custódia]

| Customer ID | Some Date  | Balance |
+-------------+------------+---------+
|           1 | 2012-04-30 |   20.00 |
|           1 | 2012-03-31 |   50.00 |
|           2 | 2012-04-30 |    0.00 |
|           2 | 2012-03-31 |   10.00 | 
|           3 | 2012-03-31 |   60.00 |
|           3 | 2012-02-29 |   10.00 |

Gostaria de obter um conjunto de resultados como este - um registro para cada cliente com a data mais recente:

| Customer ID | Some Date  | Balance |
+-------------+------------+---------+
|           1 | 2012-04-30 |   20.00 | 
|           2 | 2012-04-30 |    0.00 |
|           3 | 2012-03-31 |   60.00 |

Eu sei que posso fazer isso para cada "ID do cliente" individual com a seguinte SQL (sintaxe do SQL Server):

select top 1  [Some Date], [Customer ID], [Balance]
from [Cust Date Table]
where [Customer ID] = 2
order by [Some Date] desc


| Customer ID | Some Date  | Balance |
+-------------+------------+---------+
|           2 | 2012-04-30 |    0.00 |

Mas não tenho certeza de como obter todos os três registros que desejo. Não tenho certeza se essa é uma situação que exige uma subconsulta ou outra coisa.

Observe que a data máxima pode ser diferente para qualquer [ID do cliente], (neste exemplo, a data máxima do cliente 3 é 31/03/2012, enquanto os outros registros têm uma data máxima de 30/04/2012). eu tentei

select [Customer ID], MAX([Some Date]) AS [Latest Date], Balance 
from [Cust Date Table] 
group by [Customer ID], Balance; 

O problema é que isso não retorna apenas uma linha para cada cliente - ele retorna várias linhas.

Joe DBA
fonte

Respostas:

18

Você simplesmente quer:

SELECT
    [Customer ID],
    MAX([Some Date]) AS[Latest Date]
FROM[Cust Date TABLE]
GROUP BY
    [Customer ID];

Ok - você revisou. Agora você deseja ordenar as linhas e escolher a primeira:

WITH numbered AS (
    SELECT
        [Customer ID],
        [Some Date],
        [Balance],
        ROW_NUMBER() OVER (
            PARTITION BY
                [Customer ID]
            ORDER BY
                [Some Date] DESC
        ) AS rownum
    FROM[Cust Date TABLE]
)
SELECT
    [Customer ID],
    [Some Date],
    [Balance]
FROM numbered
WHERE
    rownum = 1;
Rob Farley
fonte
Oh - você mudou a pergunta?
Rob Farley
Mudou minha resposta agora.
Rob Farley
Uma vantagem (ou desvantagem, dependendo de seus requisitos) dessa solução é que, se a data mais recente ocorrer em mais de uma linha para o mesmo cliente, ela não produzirá resultados duplicados.
Tim
7

Eu acho que você está atrás de algo assim

select c.[customer ID], [some date], balance
from [cust date table] c
inner join 
    ( select [customer ID], MAX([some date]) as maxdate
    from [cust date table]
    group by [customer ID]) c2
on c2.[customer ID] = c.[customer ID]
and c2.maxdate = c.[some date]

Há várias variações nisso, como CTE, variável de tabela, #table, com as quais você pode brincar para ver o que oferece o melhor desempenho em sua situação.

WT_W
fonte
Esta resposta também está correta. Infelizmente, não tenho representante suficiente para fazer o voto positivo e tenho que escolher uma resposta.
Joe DBA