Vejo que muitas pessoas usam subconsultas ou funções de janela para fazer isso, mas muitas vezes faço esse tipo de consulta sem subconsultas da seguinte maneira. Ele usa SQL simples e padrão, portanto, deve funcionar em qualquer marca de RDBMS.
SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;
Em outras palavras:busque a linha de
t1 onde não existe outra linha com o mesmo UserId e uma data maior. (Coloquei o identificador "Data" nos delimitadores porque é uma palavra reservada do SQL.)
Caso
t1."Date" = t2."Date" , a duplicação aparece. Normalmente as tabelas têm auto_inc(seq) chave, por exemplo id .Para evitar a duplicação pode ser usado o seguinte:SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date")
OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;
Comentário de @Farhan:
Segue uma explicação mais detalhada:
Uma junção externa tenta ingressar em
t1 com t2 . Por padrão, todos os resultados de t1 são retornados e se há uma correspondência em t2 , ele também é retornado. Se não houver correspondência em t2 para uma determinada linha de t1 , a consulta ainda retornará a linha de t1 , e usa NULL como um espaço reservado para todos os t2 colunas de. É assim que as junções externas funcionam em geral. O truque nesta consulta é projetar a condição de correspondência da junção de forma que
t2 deve corresponder ao mesmo userid , e um maior date . A ideia é se existe uma linha em t2 que tem uma date maior , então a linha em t1 é comparado com não pode ser a maior date para esse userid . Mas se não houver correspondência -- ou seja, se não existir nenhuma linha em t2 com uma date maior do que a linha em t1 -- sabemos que a linha em t1 foi a linha com a maior date para o userid fornecido . Nesses casos (quando não há correspondência), as colunas de
t2 será NULL -- mesmo as colunas especificadas na condição de junção. É por isso que usamos WHERE t2.UserId IS NULL , porque estamos procurando os casos em que nenhuma linha foi encontrada com uma date maior para o userid fornecido .