Pergunta

Dê uma olhada na tabela MySQL abaixo chamada "Artigos":

+----+-----------+---------+------------------------+--------------------------+
| id | articleId | version | title                  | content                  |
+----+-----------+---------+------------------------+--------------------------+
|  1 |         1 | 0.0     | ArticleNo.1 title v0.0 | ArticleNo.1 content v0.0 |
|  2 |         1 | 1.0     | ArticleNo.1 title v1.0 | ArticleNo.1 content v1.0 |
|  3 |         1 | 1.5     | ArticleNo.1 title v1.5 | ArticleNo.1 content v1.5 |
|  4 |         1 | 2.0     | ArticleNo.1 title v2.0 | ArticleNo.1 content v2.0 |
|  5 |         2 | 1.0     | ArticleNo.2 title v1.0 | ArticleNo.2 content v1.0 |
|  6 |         2 | 2.0     | ArticleNo.2 title v2.0 | ArticleNo.2 content v2.0 |
+----+-----------+---------+------------------------+--------------------------+

Estou tentando criar uma consulta para retornar artigos.

A tabela de artigos reais contém mais de 10.000 entradas.

Então, neste exemplo, eu só quero que os artigos.ID 4 e 6 sejam devolvidos. Eu tenho olhado para a palavra -chave distinta e função max (), mas não consigo acertar.

Quaisquer sugestões apreciadas ...

Foi útil?

Solução

Você precisa de uma subse você aqui:

SELECT a.id, a.version
FROM articles a
WHERE a.version = (
    SELECT MAX(version)
    FROM articles b
    WHERE b.articleId = a.articleId
)

Outras dicas

De Manual MySQL, isso faz o truque:

SELECT a1.id
FROM Articles a1
LEFT JOIN Articles a2 ON a1.articleId = a2.articleId AND a1.version < a2.version
WHERE a2.articleId IS NULL;

Do manual vinculado:

o LEFT JOIN funciona com base em que quando quando s1.price a1.version está em seu máximo mínimo valor, não há s2.price a2.version com um maior menor valor e, portanto, o correspondente s2.article a2.articleId valor é NULL.

(Eu editei para fazer com que o texto corresponda à sua situação.)

Você pode usar uma subconeração aqui:

select
    a.id
from
    articles a
where
    a.version = (select max(version) from articles)

Como isso não é uma subconsulta correlacionada, será muito rápido (tão rápido ou mais rápido que uma junção), então você não precisa se preocupar com isso. Mas vai devolver todos os valores que têm o máximo articleid.

Claro, eu recomendo que você jogue um índice em articleid (assumindo id já está agrupado). Isso ajudará a voltar ainda mais rápido.

Como observado nos comentários, se você deseja obter a versão máxima para cada articleid, você pode fazer o seguinte:

select
    a.id
from
    articles a
    inner join (select articleid, max(version) 
                from articles group by articleid) as b on
        a.articleid = b.articleid
        and a.version = b.version

Isso criará uma junção dessa subconsência e normalmente será muito mais rápido do que uma subconsência correlacionada que seleciona o máximo para cada articleid.

SELECT Articles.id FROM Articles WHERE Articles.version IN (SELECT MAX(Articles.version) FROM Articles)

Talvez algo como:

Selecione * em Artigos em que o ArtigoId em (Selecione Max (ArtigoVersion) dos artigos)

Você pode fazer

SELECT articles.id
  FROM articles a
 WHERE NOT EXISTS(SELECT * FROM articles a2 WHERE a2.version > a.version)

Não sei se o MySQL executará com ele, mas o Oracle e o SQL Server estão bem com ele.

Todas as respostas acima podem resolver o problema declarado do DJDonal3000. Mas, a maioria deles são sublimes correlacionadas que dificultam o desempenho do aplicativo. Se você estiver usando um aplicativo em nuvem, sugiro não usar as consultas acima. A melhor maneira é manter duas tabelas, A e B. A contendo sempre a versão mais recente do artigo e B tendo detalhes de todas as versões. A questão é que haverá mais atualizações e inserções nas tabelas, mas a busca será mais rápida, pois você só precisar

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top