MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

5 maneiras de selecionar linhas com o valor máximo para seu grupo no SQL


Aqui estão cinco opções para usar o SQL para retornar apenas as linhas que têm o valor máximo em seu grupo.

Esses exemplos funcionam na maioria dos principais RDBMSs, incluindo MySQL, MariaDB, Oracle, PostgreSQL, SQLite e SQL Server.

Dados de amostra


Suponha que temos uma tabela com os seguintes dados:
SELECT * FROM Gameshow;

Resultado:
+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Faye         | 2      | 50      |
| Faye         | 3      | 63      |
| Jet          | 1      | 31      |
| Jet          | 2      | 40      |
| Jet          | 3      | 51      |
| Spike        | 1      | 25      |
| Spike        | 2      | 27      |
| Spike        | 3      | 15      |
+--------------+--------+---------+

E suponha que queremos obter a pontuação mais alta para cada competidor.

Opção 1


Uma opção rápida e fácil é construir uma consulta com o SQL GROUP BY cláusula:
SELECT 
    Contestant,
    MAX( Score ) AS MaxScore
FROM Gameshow
GROUP BY Contestant
ORDER BY Contestant;

Resultado:
+--------------+------------+
| Contestant   | MaxScore   |
|--------------+------------|
| Faye         | 85         |
| Jet          | 51         |
| Spike        | 27         |
+--------------+------------+

Opção 2


Se quisermos incluir o jogo que cada competidor jogou para obter a pontuação máxima, uma maneira de fazer isso é usar uma subconsulta correlacionada como esta:
SELECT 
    Contestant,
    Game,
    Score
FROM Gameshow g1
WHERE Score = ( SELECT MAX( g2.Score )
              FROM Gameshow g2
              WHERE g1.Contestant = g2.Contestant )
ORDER BY Contestant;

Resultado:
+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

As subconsultas correlacionadas referem-se a uma ou mais colunas de fora da subconsulta. Subconsultas correlacionadas podem ser ineficientes, principalmente devido ao fato de que a subconsulta é executada repetidamente, uma vez para cada linha que pode ser selecionada pela consulta externa. As subconsultas correlacionadas também são conhecidas como subconsultas de repetição.

Opção 3


Alternativamente, podemos usar uma subconsulta não correlacionada como esta:
SELECT 
    g1.Contestant, 
    g1.Game,
    g1.Score
FROM Gameshow g1
JOIN (
  SELECT Contestant, MAX( Score ) AS Score
  FROM Gameshow
  GROUP BY Contestant ) AS g2
  ON g1.Contestant = g2.Contestant AND g1.Score = g2.Score
ORDER BY Contestant ASC;

Resultado:
+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

As subconsultas não correlacionadas não dependem da consulta externa para sua execução. Eles podem ser executados de forma totalmente independente da consulta externa.

No Oracle, precisamos remover o AS ao declarar os aliases da coluna:
SELECT 
    g1.Contestant, 
    g1.Game,
    g1.Score
FROM Gameshow g1
JOIN (
  SELECT Contestant, MAX( Score ) Score
  FROM Gameshow
  GROUP BY Contestant ) g2
  ON g1.Contestant = g2.Contestant AND g1.Score = g2.Score
ORDER BY Contestant ASC;

Opção 4


Outra opção é usar um LEFT JOIN , assim:
SELECT 
    g1.Contestant, 
    g1.Game,
    g1.Score
FROM Gameshow g1
LEFT JOIN Gameshow g2 ON 
    g1.Contestant = g2.Contestant AND g1.Score < g2.Score
WHERE g2.Contestant IS NULL
ORDER BY g1.Contestant ASC;

Resultado:
+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+

Opção 5


Outra maneira de buscar linhas com o valor máximo em uma determinada coluna é usar uma expressão de tabela comum com função de janela:
WITH cte AS (
   SELECT Contestant, Game, Score,
            RANK() OVER ( PARTITION BY Contestant
            ORDER BY Score DESC
            ) AS r
    FROM Gameshow
)
SELECT Contestant, Game, Score
FROM cte
WHERE r = 1
ORDER BY Contestant ASC;

Resultado:
+--------------+--------+---------+
| Contestant   | Game   | Score   |
|--------------+--------+---------|
| Faye         | 1      | 85      |
| Jet          | 3      | 51      |
| Spike        | 2      | 27      |
+--------------+--------+---------+