Minha mesa é:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
3 | 10 | 03/03/2009 | john | 300
4 | 11 | 03/03/2009 | juliet | 200
6 | 12 | 03/03/2009 | borat | 500
7 | 13 | 24/12/2008 | borat | 600
8 | 13 | 01/01/2009 | borat | 700
Eu preciso selecionar cada distinto home
segurando o valor máximo de datetime
.
O resultado seria:
id home datetime player resource
---|-----|------------|--------|---------
1 | 10 | 04/03/2009 | john | 399
2 | 11 | 04/03/2009 | juliet | 244
5 | 12 | 04/03/2009 | borat | 555
8 | 13 | 01/01/2009 | borat | 700
Eu tentei:
-- 1 ..by the MySQL manual:
SELECT DISTINCT
home,
id,
datetime AS dt,
player,
resource
FROM topten t1
WHERE datetime = (SELECT
MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC
Não funciona O conjunto de resultados possui 130 linhas, embora o banco de dados contenha 187. O resultado inclui algumas duplicatas de home
.
-- 2 ..join
SELECT
s1.id,
s1.home,
s1.datetime,
s1.player,
s1.resource
FROM topten s1
JOIN (SELECT
id,
MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
ON s1.id = s2.id
ORDER BY datetime
Não. Dá todos os registros.
-- 3 ..something exotic:
Com vários resultados.
id
,player
eresource
de linha não-max para um determinado ie casa para casa = 10 você pode obter:3 | 10 | 04/03/2009 | john | 300
Em outras palavras, ele não garante que todas as colunas de uma linha no conjunto de resultados pertencerão para max (datetime) para determinada casa.A
MySQL
solução mais rápida , sem consultas internas e semGROUP BY
:Explicação :
Junte-se à tabela usando a
home
coluna O uso deLEFT JOIN
garante que todas as linhas da tabelam
apareçam no conjunto de resultados. Aqueles que não têm uma correspondência na tabelab
terãoNULL
s para as colunas deb
.A outra condição nas
JOIN
solicitações para corresponder apenas às linhasb
que possuem maior valor nadatetime
coluna que a linha dem
.Usando os dados postados na pergunta, o
LEFT JOIN
produzirá estes pares:Por fim, a
WHERE
cláusula mantém apenas os pares que possuemNULL
s nas colunas deb
(eles são marcados com*
na tabela acima); isso significa que, devido à segunda condição daJOIN
cláusula, a linha selecionadam
possui o maior valor na colunadatetime
.Leia o livro Antipatterns SQL: Evitando as armadilhas da programação de banco de dados para obter outras dicas sobre SQL.
fonte
SQLite
, o primeiro é muito mais lento que a versão de La Voie, quando não há índice na coluna correspondente (ou seja, "casa"). (Testado com 24k linhas resultando em 13k linhas)home
edatetime
edatetime
é o máximo para que determinadohome
?ON
cláusula. Fe... ON ... AND m.id < b.id
para manter a entrada mais recente (aquela com a maiorid
) quando duas linhas tiverem os mesmos valores emhome
edatetime
colunas e é o máximodatetime
.Aqui está a versão T-SQL :
EDITAR
Infelizmente, não há função RANK () OVER no MySQL.
Mas pode ser emulado, consulte Emulando funções analíticas (Ranking AKA) com o MySQL .
Então esta é a versão do MySQL :
fonte
Isso funcionará mesmo se você tiver duas ou mais linhas para cada uma
home
com iguaisDATETIME
:fonte
WHERE ti.home = t1.home
- você pode explicar a sintaxe?select
consulta que tem a linhaWHERE ti.home = t1.home
não precisa daFROM
cláusula que definet1
. Então, como é usado?Eu acho que isso lhe dará o resultado desejado:
MAS, se você precisar de outras colunas, faça uma junção com a tabela original (verifique a
Michael La Voie
resposta)Cumprimentos.
fonte
Como as pessoas parecem continuar seguindo esse segmento (a data dos comentários varia de 1,5 ano) não é muito mais simples:
SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home
Nenhuma função de agregação é necessária ...
Felicidades.
fonte
Você também pode tentar este e para tabelas grandes o desempenho da consulta será melhor. Funciona quando não há mais de dois registros para cada casa e suas datas são diferentes. Melhor consulta geral do MySQL é de Michael La Voie acima.
Ou, no caso do Postgres ou dos dbs que fornecem funções analíticas, tente
fonte
SQLite
, o primeiro é muito mais lento que a versão de La Voie, quando não há índice na coluna correspondente (ou seja, "casa").Isso funciona no Oracle:
fonte
fonte
Tente isso para o SQL Server:
fonte
fonte
Aqui está a versão do MySQL que imprime apenas uma entrada em que há duplicatas MAX (datetime) em um grupo.
Você poderia testar aqui http://www.sqlfiddle.com/#!2/0a4ae/1
Dados de amostra
Versão MySQL com variável User
Saída das respostas aceitas
fonte
Outra maneira de obter a linha mais recente por grupo usando uma subconsulta que basicamente calcula uma classificação para cada linha por grupo e depois filtra as linhas mais recentes como com rank = 1
DEMO
Aqui está a demonstração visual da classificação não para cada linha para melhor compreensão
A consulta acima falhará e retornará mais de 1 linha para a situação acima. Para encobrir esta situação, haverá a necessidade de outro critério / parâmetro / coluna para decidir qual linha deve ser tomada e qual se enquadra na situação acima. Ao visualizar o conjunto de dados de amostra, presumo que exista uma coluna de chave primária
id
que deve ser configurada para incremento automático. Portanto, podemos usar esta coluna para escolher a linha mais recente, ajustando a mesma consulta com a ajuda deCASE
instruções comoDEMO
A consulta acima selecionará a linha com o ID mais alto entre os mesmos
datetime
valoresdemonstração visual para a classificação não para cada linha
fonte
Por que não usar: SELECT home, MAX (datetime) AS MaxDateTime, player, resource FROM topten GROUP BY home Perdi alguma coisa?
fonte
expected
saída no MySQL versão 5.6before
e eu duvido que ele se comporte de outra maneira no MySQL versão 5.7 eafter
.Tente isto
Atenciosamente K
fonte
max(datetime)
édatetime
. Não vai causar nenhum problema?datetime
selecionada?esta é a consulta que você precisa:
fonte
@ Michae A resposta aceita funcionará bem na maioria dos casos, mas falha em uma, conforme abaixo.
Caso existam 2 linhas com HomeID e Datetime iguais, a consulta retornará ambas as linhas, não HomeID distintas, conforme necessário, para que adicione Distinct na consulta, como abaixo.
fonte
Espero que a consulta abaixo dê a saída desejada:
fonte