2012-10-27 10 views
8

Diciamo che ho una tabella impianto:Cosa può fare una funzione di aggregazione nella clausola ORDER BY?

id fruit 
1 banana 
2 apple 
3 orange 

posso fare questi

SELECT * FROM plant ORDER BY id; 
SELECT * FROM plant ORDER BY fruit DESC; 

che fa la cosa più ovvia.

Ma sono stato morso da questo, cosa fa questo?

SELECT * FROM plant ORDER BY SUM(id); 
SELECT * FROM plant ORDER BY COUNT(fruit); 
SELECT * FROM plant ORDER BY COUNT(*); 
SELECT * FROM plant ORDER BY SUM(1) DESC; 

Tutti questi restituiscono solo la prima riga (che è con id = 1).

  1. Cosa sta succedendo underhood?
  2. Quali sono gli scenari in cui la funzione di aggregazione sarà utile in ORDER BY?

risposta

12

I suoi risultati sono più chiare se effettivamente selezionare i valori aggregati in luogo delle colonne della tabella:

SELECT SUM(id) FROM plant ORDER BY SUM(id) 

Ciò restituirà la somma di tutti id. Questo è ovviamente un esempio inutile perché l'aggregazione creerà sempre solo una riga, quindi non c'è bisogno di ordinare. Il motivo per cui ottieni una riga con le colonne nella tua query è perché MySQL sceglie una riga, non a caso ma non deterministica. Si dà il caso che sia la prima colonna della tabella nel tuo caso, ma altri potrebbero ottenere un'altra riga a seconda del motore di archiviazione, delle chiavi primarie e così via. L'aggregazione solo nella clausola ORDER BY non è quindi molto utile.

quello che di solito vuole fare è il raggruppamento di un certo campo e poi ordinare il set di risultati in qualche modo:

SELECT fruit, COUNT(*) 
FROM plant 
GROUP BY fruit 
ORDER BY COUNT(*) 

Ora che è una query più interessante! Questo ti darà una riga per ogni frutto insieme al conteggio totale per quel frutto. Prova ad aggiungere qualche altro mele e l'ordine sarà effettivamente iniziare a fare senso:

Tabella completa:

+----+--------+ 
| id | fruit | 
+----+--------+ 
| 1 | banana | 
| 2 | apple | 
| 3 | orange | 
| 4 | apple | 
| 5 | apple | 
| 6 | banana | 
+----+--------+ 

La query sopra:

+--------+----------+ 
| fruit | COUNT(*) | 
+--------+----------+ 
| orange |  1 | 
| banana |  2 | 
| apple |  3 | 
+--------+----------+ 
+0

Ottima spiegazione, grazie! – nawfal

2
  1. Quando si utilizza un aggregato del genere, la query ottiene un gruppo implicito in base al quale l'intero risultato è un singolo gruppo.

  2. L'utilizzo di un aggregato in ordine è utile solo se si dispone anche di un gruppo per, in modo da poter avere più di una riga nel risultato.

2

Tutte queste query forniranno tutti un errore di sintassi su qualsiasi piattaforma SQL conforme agli standard SQL.

SELECT * FROM plant ORDER BY SUM(id); 
SELECT * FROM plant ORDER BY COUNT(fruit); 
SELECT * FROM plant ORDER BY COUNT(*); 
SELECT * FROM plant ORDER BY SUM(1) DESC; 

Su PostgreSQL, ad esempio, tutte le query generano lo stesso errore.

ERROR: column "plant.id" must appear in the GROUP BY clause or be used in an aggregate function

Ciò significa che stai utilizzando una funzione di aggregazione del dominio senza utilizzare GROUP BY. SQL Server e Oracle restituiscono messaggi di errore simili.

MySQL's GROUP BY è noto per essere rotto in diversi aspetti, almeno per quanto riguarda il comportamento standard. Ma le domande che hai postato sono state un nuovo comportamento interrotto, quindi +1 per quello.

Invece di cercare di capire cosa sta facendo sotto il cofano, probabilmente stai meglio imparando a scrivere query GROUP BY standard. MySQL corrisponderà alle istruzioni standard GROUP BY dello per quanto ne so.

Le versioni precedenti di documenti MySQL ti avvisavano di GROUP BY e colonne nascoste. (Non ho un punto di riferimento, ma questo testo è citato in tutto il luogo.)

Do not use this feature if the columns you omit from the GROUP BY part are not constant in the group. The server is free to return any value from the group, so the results are indeterminate unless all values are the same.

More recent versions are a little different.

You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.

Personalmente, non ritengo indeterminata una funzionalità di SQL.

Problemi correlati