Vejo muitas pessoas usarem subconsultas ou outros recursos específicos do fornecedor para fazer isso, mas geralmente 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 t1onde não existe outra linha com a mesma data UserIde uma data maior.
(Coloquei o identificador "Data" nos delimitadores porque é uma palavra reservada ao SQL.)
Caso isso t1."Date" = t2."Date"ocorra, a duplicação será exibida. Normalmente, as tabelas têm auto_inc(seq)chave, por exemplo id. Para evitar a duplicação pode ser usado a seguir:
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;
Re comentário de @Farhan:
Aqui está uma explicação mais detalhada:
Uma junção externa tentativas para se juntar t1com t2. Por padrão, todos os resultados de t1são retornados e, se houver uma correspondência t2, ele também será retornado. Se não houver correspondência t2para uma determinada linha de t1, a consulta ainda retornará a linha de t1e será usada NULLcomo espaço reservado para todas t2as 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, que t2deve corresponder à mesma userid e maior date . A ideia é que, se existir uma linha t2com uma maior date, então a linha na qual t1ela é comparada não pode ser a melhor datepara isso userid. Mas se não houver correspondência - ou seja, se nenhuma linha existir t2com uma maior dateque a linha exibida t1-, sabemos que a linha in t1foi a linha com a maior datepara o dado userid.
Nesses casos (quando não há correspondência), as colunas t2serão NULL- mesmo as colunas especificadas na condição de junção. É por isso que usamos WHERE t2.UserId IS NULL, porque estamos pesquisando os casos em que nenhuma linha foi encontrada com uma maior datepara o dado userid.