Selecione um valor de um grupo com base na ordem de outras colunas

Problema

Suponha que eu tenha esta tabelatab (violino acessível).

| g | a | b |     v |
---------------------
| 1 | 3 | 5 |   foo |
| 1 | 4 | 7 |   bar |
| 1 | 2 | 9 |   baz |
| 2 | 1 | 1 |   dog |
| 2 | 5 | 2 |   cat |
| 2 | 5 | 3 | horse |
| 2 | 3 | 8 |   pig |

Estou agrupando linhas porg, e para cada grupo eu quero um valor da colunav. No entanto, eu não queroqualquer valor, mas eu quero o valor da linha com o máximoa, e de todos esses, aquele com maximalb. Em outras palavras, meu resultado deve ser

| 1 |   bar |
| 2 | horse |
Solução atual

Eu sei de uma consulta para conseguir isso:

SELECT grps.g,
(SELECT v FROM tab
 WHERE g = grps.g
 ORDER BY a DESC, b DESC
 LIMIT 1) AS r
FROM (SELECT DISTINCT g FROM tab) grps
Questão

Mas eu considero essa consultafeio. Principalmente porque usa umsubconsulta dependente, que parece um verdadeiro matador de performance. Então, eu me pergunto se existe uma solução mais fácil para esse problema.

Respostas esperadas

A resposta mais provável que eu espero para essa pergunta seria algum tipo de complemento ou patch para o MySQL (ou MariaDB) que fornece um recurso para isso. Mas também receberei outras inspirações úteis. Qualquer coisa que funcione sem uma subconsulta dependente se qualifica como uma resposta.

Se a sua solução só funciona para uma única coluna de pedido, ou seja, não foi possível distinguir entrecat ehorse, sinta-se à vontade para sugerir essa resposta, assim como espero que ainda seja útil para a maioria dos casos de uso. Por exemplo,100*a+b seria uma maneira provável de ordenar os dados acima por ambas as colunas enquanto ainda estiver usando apenas uma única expressão.

Eu tenho algumas soluções bem legais em mente, e posso acrescentá-las depois de um tempo, mas primeiro vou ver e ver se algumas boas novas vão aparecer primeiro.

Resultados de referência

Como é muito difícil comparar as várias respostas apenas olhando para elas, eu fiz algumas referências sobre elas. Isso foi executado no meu próprio desktop, usando o MySQL 5.1. Os números não se comparam a nenhum outro sistema, apenas um ao outro. Você provavelmente deveria estar fazendo seus próprios testes com seus dados da vida real se o desempenho for crucial para o seu aplicativo. Quando novas respostas chegam, posso adicioná-las ao meu script e executar novamente todos os testes.

100.000 itens, 1.000 grupos para escolher, InnoDb:0,166s paraMvG (da pergunta)0,520s paraRichardTheKiwi2.199 paraxdazz19,24s paraDems (sub-consultas sequenciais)48,72s paraacatt100.000 itens, 50.000 grupos para escolher, InnoDb:0,356 paraxdazz0,640s paraRichardTheKiwi0,764s paraMvG (da pergunta)51,50s paraacattdemasiado longo paraDems (sub-consultas sequenciais)100.000 itens, 100 grupos para escolher, InnoDb:0,163s paraMvG (da pergunta)0,523s paraRichardTheKiwi2,072s paraDems (sub-consultas sequenciais)17,78s paraxdazz49,85s paraacatt

Portanto, parece que minha solução até agora não é tão ruim assim, mesmo com a subconsulta dependente. Surpreendentemente, a solução por acatt, que também usa uma subconsulta dependente e que eu, portanto, consideraria sobre a mesma, tem um desempenho muito pior. Provavelmente algo que o otimizador do MySQL não suporta. A solução proposta por RichardTheKiwi parece ter bom desempenho geral também. As outras duas soluções dependem muito da estrutura dos dados. Com muitos grupos de grupos pequenos, a abordagem do xdazz supera todos os outros, enquanto a solução da Dems tem melhor desempenho (embora ainda não seja excepcionalmente boa) para alguns grupos grandes.

questionAnswers(4)

yourAnswerToTheQuestion