Como encontrar itens associados ao maior ou ao menor valor de uma lista no MySQL

Para listar itens e ainda associá-los aos maiores ou menores valores use funções do MySQL em conjunto com as funções MAX() e MIN().
Veja alguns exemplos em que 2 queries são combinadas para obter resultados mais significativos.
As funções MIN() e MAX() são úteis para encontrar os extremos de uma relação de valores. O problema é que, ás vezes, queremos também saber a que item na tabela o valor em questão se encontra associado.
em uma relação de clientes correntistas, podemos usar a função MAX() para determinar qual o maior valor de crédito. O problema a ser resolvido é o de determinar exatamente a quem pertence o tal valor.
Veja um exemplo prático, no qual vamos determinar qual o maior valor de créditos possuído por cliente, na tabela CadastroClientes:

SELECT MAX(CreditosCliente) FROM CadastroClientes;

Como você pode ver, abaixo, o maior valor é 4992:

+----------------------+
| MAX(CreditosCliente) |
+----------------------+
|                 4992 |
+----------------------+
1 row in set (0.01 sec)

E se você quiser saber a que cliente este valor está associado?
Uma das soluções mais óbvias seria a seguinte:

SELECT NomeCliente, MAX(CreditosCliente) FROM CadastroClientes WHERE CreditosCliente = MAX(CreditosClente);

ERROR 1111 (HY000): Invalid use of group function

Infelizmente, ela não funciona.
Por mais que a lógica desta query pareça boa (ela não é), o fato é que funções agregadas, tais como MIN() e MAX(), não podem ser usadas em cláusulas WHERE.
A intenção da consulta é determinar qual registro tem o maior valor de crédito e exibir o nome do cliente associado a este valor.
O problema é que enquanto eu e você entendemos a consulta, pro MySQL ela não faz sentido algum.
Ela não funcionou porque, o MySQL usa a cláusla WHERE para determinar quais registros selecionar, mas só conhece o valor de uma função agregada depois de selecionar os registros a partir dos quais o valor da função é determinado.
A declaração se contradiz, portanto.
A solução, abaixo, é uma gambiarra e, embora chegue à conclusão correta, não responde diretamente ao enunciado:

SELECT NomeCliente, CreditosCliente FROM CadastroClientes ORDER BY CreditosCliente DESC LIMIT 1;
+------------------+-----------------+
| NomeCliente      | CreditosCliente |
+------------------+-----------------+
| Camille Thornton |            4992 |
+------------------+-----------------+
1 row in set (0.00 sec)

Você pode solucionar o problema usando uma abordagem em 2 estágios ou um subselect.
No primeiro estágio, atribuo o maior valor de créditos da tabela à variável CreditoMax:

SELECT @CreditoMax := MAX(CreditosCliente) FROM CadastroClientes;
+-------------------------------------+
| @CreditoMax := MAX(CreditosCliente) |
+-------------------------------------+
|                                4992 |
+-------------------------------------+
1 row in set (0.00 sec)

No segundo estágio, já tenho condições de criar uma consulta que encontre o valor máximo, relacionado ao cliente:

SELECT NomeCliente AS Cliente, @CreditoMax AS "Créditos" FROM CadastroClientes WHERE CreditosCliente = @CreditoMax;
+------------------+-----------+
| Cliente          | Créditos  |
+------------------+-----------+
| Camille Thornton |      4992 |
+------------------+-----------+
1 row in set (0.00 sec)

Nas versões mais atuais do MySQL, é possível resolver o problema com uma subselect, em apenas uma linha de código:

SELECT NomeCliente AS Cliente, CreditosCliente AS "Créditos" FROM CadastroClientes WHERE CreditosCliente = (SELECT MAX(CreditosCliente) FROM CadastroClientes);
+------------------+----------+
| Cliente          | Créditos |
+------------------+----------+
| Camille Thornton |     4992 |
+------------------+----------+
1 row in set (0.00 sec);

Mais um exemplo

No próximo exemplo, vou usar uma tabela que contém a Bíblia.
O objetivo é estabelecer qual o menor versículo presente no livro.
Primeiro, vamos estabelecer quantos caracteres tem o menor versículo da bíblia:

SELECT MIN(LENGTH(textover)) FROM bibliakjv;
+-----------------------+
| MIN(LENGTH(textover)) |
+-----------------------+
|                    13 |
+-----------------------+
1 row in set (0.02 sec)

Que tal uma resposta mais completa — que mostre a quantidade de caracteres do menor versículo da bíblia e o texto do mesmo?
Novamente, vejamos como solucionar o problema em 2 estágios (definindo uma variável e operando com ela, em seguida):

SELECT @MenorVerso := MIN(LENGTH(textover)) FROM bibliakjv;
+--------------------------------------+
| @MenorVerso := MIN(LENGTH(textover)) |
+--------------------------------------+
|                                   13 |
+--------------------------------------+
1 row in set (0.01 sec)

Uma vez atribuído o valor da menor quantidade de caracteres à variável @MenorVerso, vamos usá-lo na próxima consulta:

SELECT numliv AS "Livro", numcap AS "Capítulo", numver AS "Versículo", textover AS "Texto do versículo" FROM bibliakjv WHERE LENGTH(textover) = @MenorVerso\G
*************************** 1. row ***************************
             Livro: 5
          Capítulo: 5
         Versículo: 17
Texto do versículo: Não matarás. 
Núm. de caracteres: 13
1 row in set (0.02 sec)

Note que, na minha versão da Bíblia, há um espaço a mais no versículo, logo após o ponto final — que é contado e, portanto, dá 13 caracteres ao versículo. Paciência… 😉
Se você prefere uma solução usando uma subquery, lá vai:

SELECT numliv AS "Livro", numcap AS "Capítulo", numver AS "Versículo", textover AS "Texto do versículo", @MenorVerso AS "Núm. de caracteres" FROM bibliakjv WHERE LENGTH(textover) = (SELECT MIN(LENGTH(textover)) FROM bibliakjv)\G
*************************** 1. row ***************************
             Livro: 5
          Capítulo: 5
         Versículo: 17
Texto do versículo: Não matarás.
Núm. de caracteres: 13
1 row in set (0.05 sec)

Use DISTINCT para eliminar redundâncias no MySQL

O DISTINCT pode ser usado para determinar quantos valores redundantes há numa lista ou, pelo contrário, quantos valores distintos há presentes.
Use a cláusula DISTINCT para selecionar os valores únicos ou agregue funções com COUNT(DISTINCT) para contá-los.
O DISTINCROW, caso você já tenha ouvido falar, é sinônimo do DISTINCT — use o que te deixa mais confortável, portanto.
Um relatório que não use funções agregadas é usado para determinar quais valores ou quais registros estão contidos no banco de dados, pela eliminação das redundâncias.
O DISTINCT é útil para reduzir o resultado de uma declaração à sua essência. Pode ser combinado com ORDER BY para ordenar a lista.
Por exemplo, se quiser saber os nomes dos clientes listados na tabela de cli_tabela, use a seguinte consulta:

SELECT DISTINCT cli_nome FROM cli_tabela ORDER BY cli_nome;
_
+----------+
| cli_nome |
+----------+
| Ian      |
| Henry    |
| Justin   |
+----------+

Uma declaração sem o uso da cláusula DISTINCT e ORDER BY produz uma relação com os mesmos nomes, só que não é tão fácil de entender.
Veja como ficaria:

SELECT cli_nome FROM cli_tabela;
_

O resultado contém informação demais e fora de ordem:

+----------+
| cli_nome |
+----------+
| Ian      |
| Justin   |
| Henry    |
| Henry    |
| Ian      |
| Henry    |
| Justin   |
| Henry    |
| Ian      |
| Henry    |
+----------+

Mesmo a relação contendo 10 registros de nomes de clientes, temos na verdade apenas 3 nomes de clientes nesta relação.
Se você quiser obter apenas uma contagem dos nomes de clientes registrados na tabela, use COUNT(DISTINCT). Veja um exemplo:

SELECT COUNT(DISTINCT cli_nome) FROM cli_tabela;

como já sabemos, o resultado é…

+--------------------------+
| COUNT(DISTINCT cli_nome) |
+--------------------------+
|                        3 |
+--------------------------+

A cláusula COUNT(DISTINCT) ignora valores NULL.
Se, por acaso, você tiver interesse em incluir na conta estes tipos de valores, experimente o seguinte artifício:

Substitua, na query acima, a variável valor pelo campo desejado.
As consultas com DISTINCT, comumente são úteis quando combinadas com funções agregadas — podendo produzir uma caracterização mais completa de seus resultados.
Por exemplo, o uso da função COUNT(*) em uma tabela de clientes indica a quantidade de clientes presente.
Ao aplicar DISTINCT aos campos ‘estado’, por exemplo, revela-se em quais estados você tem clientes.
Se usar a combinação COUNT(DISTINCT), então, é possível saber por quantos estados se estende sua clientela.
Ao ser usado com múltiplas colunas, o DISTINCT mostra as diferentes combinações de valores e COUNT(DISTINCT) conta o número de combinações.

Como somar valores no MySQL

Em uma coluna ou em um conjunto de números, pode ser necessário determinar a soma. Use a função SUM() do MySQL para realizar esta operação.
Para começar o texto com um exemplo, veja um envolvendo todos os valores da coluna ‘CreditCliente’, que contem uma relação de créditos dos clientes na tabela ‘clientesEstaduais‘.

SELECT SUM(CreditCliente) FROM clientesEstaduais;
+--------------------+
| SUM(CreditCliente) |
+--------------------+
|             946227 |
+--------------------+

Veja a relação de clientes do Ceará (CE):

SELECT * FROM clientesEstaduais WHERE RegiaoCliente = 'CE';
+----+---------------+---------------+--------------+---------------+
| id | NomeCliente   | RegiaoCliente | DataCadastro | CreditCliente |
+----+---------------+---------------+--------------+---------------+
| 10 | Chloe Gibbs   | CE            | 2016-05-11   |          8165 |
| 14 | Winter Carson | CE            | 2016-12-10   |          2524 |
| 53 | Alea Byrd     | CE            | 2016-02-11   |          5592 |
| 76 | Taylor Ingram | CE            | 2016-06-19   |         15843 |
| 94 | Tanya Barr    | CE            | 2016-01-20   |          3252 |
+----+---------------+---------------+--------------+---------------+

Agora veja a soma de todos os seus créditos:

SELECT SUM(creditCliente) AS "Créditos CE" FROM clientesEstaduais WHERE RegiaoCliente = 'CE';
+--------------+
| Créditos CE  |
+--------------+
|        35376 |
+--------------+

Para ver todos os créditos referentes a um mês (de qualquer dia e qualquer ano):

SELECT SUM(creditCliente) AS "Créditos de Agosto" FROM clientesEstaduais WHERE MONTH(DataCadastro)='08';
+---------------------+
| Créditos de Agosto  |
+---------------------+
|              134245 |
+---------------------+

Como encontrar o maior ou o menor valor de uma lista no MySQL

As funções MIN() e MAX() podem ser usadas para encontrar o maior e o menor valor, respectivamente, dentro de uma lista de valores, no MySQL.
De certa forma, esta solução se equipara a organizar uma lista do menor valor para o maior (ou vice-versa) — e, destes itens, você escolhe apenas o primeiro valor, em vez de todos.
Este tipo de operação é feita para responder a perguntas como:

  • Qual o menor…
  • Qual o maior…
  • Qual o mais antigo…
  • Qual o mais recente…
  • Qual o mais caro…
  • Qual o mais barato…
  • etc.

Uma outra forma de resolver esta questão é com o uso da cláusula LIMIT.
As funções MIN() e MAX(), por determinarem os valores extremos de um conjunto são apropriadas para determinar limites numéricos.
Veja um exemplo, para determinar o primeiro e o último cadastro, o maior e o menor valor de crédito em uma tabela:

SELECT MIN(DataCadastro) AS "Primeiro cadastro",
    -> MAX(DataCadastro) AS "Cadastro mais recente",
    -> MIN(CreditCliente) AS "Menor valor de crédito",
    -> MAX(CreditCliente) AS "Maior valor de crédito"
    -> FROM clientesEstaduais;
+-------------------+-----------------------+-------------------------+-------------------------+
| Primeiro cadastro | Cadastro mais recente | Menor valor de crédito  | Maior valor de crédito  |
+-------------------+-----------------------+-------------------------+-------------------------+
| 2016-01-09        | 2016-12-21            |                     385 |                   19637 |
+-------------------+-----------------------+-------------------------+-------------------------+

Qual cliente tem o maior nome?

SELECT MIN(LENGTH(NomeCliente)) AS "Menor nome",
    -> MAX(LENGTH(NomeCliente)) AS "Maior nome"
    -> FROM clientesEstaduais;
+------------+------------+
| Menor nome | Maior nome |
+------------+------------+
|          8 |         19 |
+------------+------------+

Como contar ocorrências e encontrar informações redundantes no MySQL

A função COUNT() pode ser usada para encontrar dados redundantes ou determinar a quantidade de vezes que uma informação se encontra inserida em uma tabela.
Pode vir acompanhada da cláusula GROUP BY para agrupar as ocorrências, na lista — o que torna o relatório mais fácil de compreender.
Se esta situação for um problema para você, leia o artigo Como eliminar registros duplicados no MySQL, para entender como resolvê-la.
Neste texto, vou usar exemplos com a seguinte tabela (vista parcialmente):

SELECT * FROM clientesEstaduais LIMIT 10;
+----+------------------+---------------+--------------+---------------+
| id | NomeCliente      | RegiaoCliente | DataCadastro | CreditCliente |
+----+------------------+---------------+--------------+---------------+
|  1 | Kiara Meadows    | SP            | 2010-11-30   |          2614 |
|  2 | Iris Moreno      | SP            | 2013-03-05   |         13818 |
|  3 | Camilla Klein    | GO            | 2011-04-08   |          4954 |
|  4 | Stephanie Thomas | BA            | 2014-10-06   |          1678 |
|  5 | Emerald Alston   | PE            | 2013-12-02   |         12574 |
|  6 | Nevada Phelps    | PR            | 2014-07-26   |          5080 |
|  7 | Nita Solomon     | MG            | 2013-04-15   |          2267 |
|  8 | Suki Ayers       | MG            | 2014-10-08   |         12884 |
|  9 | Camille Ray      | RS            | 2013-07-11   |         13807 |
| 10 | Chloe Gibbs      | CE            | 2012-11-06   |          8165 |
+----+------------------+---------------+--------------+---------------+
10 rows in set (0.00 sec)

A tabela clientesEstaduais, pode ser encontrada aqui.

A função COUNT() do MySQL

A sintaxe da função é simples: COUNT(expressão).
Veja como contar a quantidade de registros da tabela clientesEstaduais:

SELECT COUNT(*) AS "Qtd. de registros" FROM clientesEstaduais;
+-------------------+
| Qtd. de registros |
+-------------------+
|               100 |
+-------------------+

Veja outras perguntas que podem ser respondidas com o uso da função COUNT() aliada à cláusula WHERE
Quantos clientes são do estado do Paraná (PR)?

SELECT COUNT(*) AS "Clientes do PR" FROM clientesEstaduais WHERE RegiaoCliente = 'PR';
+----------------+
| Clientes do PR |
+----------------+
|              6 |
+----------------+

Quantos clientes foram cadastros em Agosto (em qualquer dia/ano)?

SELECT COUNT(*) AS "Clientes de Agosto" FROM clientesEstaduais WHERE MONTH(DataCadastro)='08';
+--------------------+
| Clientes de Agosto |
+--------------------+
|                 12 |
+--------------------+

Quantos clientes têm mais de 15 mil em créditos?

SELECT COUNT(*) AS "> 15.000" FROM clientesEstaduais WHERE CreditCliente > 15000;
+----------+
| > 15.000 |
+----------+
|       19 |
+----------+

A função COUNT(), tem 2 formas.
A que temos usado, até agora, serve para contar as linhas da tabela: COUNT(*).
A outra forma usa uma expressão, como argumento e é usada para contar os valores não NULL ou non-NULL.
Em outras palavras, registros que contenham o campo NULL, não entram na conta, quando a expressão é dada como argumento.
Veja um exemplo:

SELECT COUNT(*) AS "Núm. de clientes",
    -> COUNT(DataCadastro) AS "Clientes cadastrados"
    -> FROM clientesEstaduais;

Uma vez que 2 clientes têm data de cadastro vazia (DataCadastro = NULL), a segunda coluna só irá contar 98:

+-------------------+----------------------+
| Núm. de clientes  | Clientes cadastrados |
+-------------------+----------------------+
|               100 |                   98 |
+-------------------+----------------------+

Como usar COUNT() com a cláusula GROUP BY

Além de ver os valores, você pode listar os registros, para ter um relatório mais rico.
No exemplo, abaixo, veja como obter a relação de estados presentes no cadastro de clientes, a quantidade de clientes por estado e em ordem descendente:

SELECT RegiaoCliente AS "Estados",
    -> COUNT(*) AS "Núm. de clientes"
    -> FROM clientesEstaduais
    -> GROUP BY RegiaoCliente
    -> ORDER BY COUNT(*) DESC;
+---------+-------------------+
| Estados | Núm. de clientes  |
+---------+-------------------+
| SP      |                30 |
| MG      |                18 |
| BA      |                10 |
| RJ      |                 9 |
| PR      |                 6 |
| RS      |                 6 |
| PE      |                 5 |
| CE      |                 5 |
| GO      |                 5 |
| MA      |                 3 |
| PA      |                 2 |
| PB      |                 1 |
+---------+-------------------+

No mês de Agosto, em quais datas houve maior número de cadastros?

SELECT DataCadastro,
    -> COUNT(*) FROM clientesEstaduais
    -> WHERE MONTH(DataCadastro)='08'
    -> GROUP BY DataCadastro
    -> ORDER BY COUNT(*) DESC;
+--------------+----------+
| DataCadastro | COUNT(*) |
+--------------+----------+
| 2016-08-21   |        2 |
| 2016-08-15   |        2 |
| 2016-08-11   |        2 |
| 2016-08-19   |        1 |
| 2016-08-16   |        1 |
| 2016-08-20   |        1 |
| 2016-08-13   |        1 |
| 2016-08-17   |        1 |
| 2016-08-09   |        1 |
+--------------+----------+