Problema:
Hai raggruppato i tuoi dati con GROUP BY e vorrei visualizzare solo la prima riga di ogni gruppo.
Esempio:
Il nostro database ha una tabella denominata exam_results con i dati nella tabella seguente:
| first_name | cognome | risultato | |
|---|---|---|---|
| Giovanni | Klein | 2020 | 40 |
| Modifica | Nero | 2020 | 43 |
| Segna | Johnson | 2019 | 32 |
| Laura | Estate | 2020 | 35 |
| Kate | Fabio | 2019 | 41 |
| Giacobbe | Nero | 2019 | 44 |
| Tom | Bennett | 2020 | 38 |
| Emilia | Kelly | 2020 | 43 |
Per ogni anno, troviamo lo studente con il miglior result . Se ci sono due studenti a pari merito in un gruppo, ne selezioneremo arbitrariamente uno da visualizzare.
Soluzione:
WITH added_row_number AS (
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results
)
SELECT
*
FROM added_row_number
WHERE row_number = 1;
Il risultato è:
| first_name | cognome | risultato | numero_riga | |
|---|---|---|---|---|
| Giacobbe | Nero | 2019 | 44 | 1 |
| Emilia | Kelly | 2020 | 43 | 1 |
Discussione:
Innanzitutto, devi scrivere un CTE in cui assegni un numero a ciascuna riga all'interno di ciascun gruppo. Per farlo, puoi utilizzare il ROW_NUMBER() funzione. In OVER() , specifichi i gruppi in cui devono essere divise le righe (PARTITION BY ) e l'ordine in cui i numeri devono essere assegnati alle righe (ORDER BY ).
Dai un'occhiata al risultato della query interna:
SELECT *, ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number FROM exam_results;
| first_name | cognome | risultato | numero_riga | |
|---|---|---|---|---|
| Giacobbe | Nero | 2019 | 44 | 1 |
| Kate | Fabio | 2019 | 41 | 2 |
| Segna | Johnson | 2019 | 32 | 3 |
| Emilia | Kelly | 2020 | 43 | 1 |
| Modifica | Nero | 2020 | 43 | 2 |
| Giovanni | Klein | 2020 | 40 | 3 |
| Tom | Bennett | 2020 | 38 | 4 |
| Laura | Estate | 2020 | 35 | 5 |
Assegni i numeri di riga all'interno di ciascun gruppo (ad esempio, anno). Ogni riga ha un numero di riga basato sul valore del result colonna. Le righe sono ordinate in ordine decrescente a causa di DESC parola chiave dopo ORDER BY result . Anche se all'interno di un gruppo sono presenti più righe che hanno lo stesso valore di result , alle righe vengono comunque assegnati numeri diversi. Qui, Edith Black ed Emily Kelly hanno lo stesso result ma numeri di riga diversi. Per modificare questo comportamento e assegnare lo stesso numero di riga per lo stesso risultato all'interno di un gruppo, usa RANK() o DENSE_RANK() invece di ROW_NUMBER() .
Nella query esterna, selezioni tutti i dati dal CTE (added_row_number ) e utilizzare un WHERE condizione per specificare quale riga visualizzare da ciascun gruppo. Qui, vogliamo visualizzare la prima riga, quindi la condizione è row_number = 1 .
Tieni presente che puoi facilmente modificare la soluzione per ottenere, ad esempio, la seconda riga di ogni gruppo.
WITH added_row_number AS (
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY year ORDER BY result DESC) AS row_number
FROM exam_results
)
SELECT
*
FROM added_row_number
WHERE row_number = 2;
Ecco il risultato:
| first_name | cognome | risultato | numero_riga | |
|---|---|---|---|---|
| Kate | Fabio | 2019 | 41 | 2 |
| Modifica | Nero | 2020 | 43 | 2 |
D'altra parte, se vuoi ottenere le righe con il secondo valore più alto di result all'interno di ogni gruppo, dovresti usare DENSE_RANK() funzione. Mentre il ROW_NUMBER() la funzione crea numeri consecutivi per ogni riga in un gruppo, risultando in valori diversi assegnati alle righe con lo stesso risultato, il DENSE_RANK() La funzione assegna lo stesso numero alle righe con lo stesso risultato.
WITH added_dense_rank AS (
SELECT
*,
DENSE_RANK() OVER(PARTITION BY year ORDER BY result DESC) AS rank
FROM exam_results
)
SELECT
*
FROM added_dense_rank
WHERE rank = 2;
| first_name | cognome | risultato | grado | |
|---|---|---|---|---|
| Kate | Fabio | 2019 | 41 | 2 |
| Giovanni | Klein | 2020 | 40 | 2 |
Puoi vedere che John Klein ha il secondo valore più alto di result (40) per l'anno 2020. John Klein è in realtà la terza persona del gruppo, ma i primi due studenti hanno lo stesso result ed entrambi hanno rank = 1 .