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 .