Perché utilizziamo Raggruppa per 1 e Raggruppa per 1,2,3 nella query SQL?


26

Nelle query SQL, utilizziamo la clausola Raggruppa per per applicare funzioni aggregate.

  • Ma qual è lo scopo dietro l'utilizzo del valore numerico invece del nome della colonna con la clausola Raggruppa per? Ad esempio: Raggruppa per 1.

3
Utilizzare order by 1solo quando ci si siede al mysql> prompt. Nel codice, utilizzare ORDER BY id ASC. Nota il caso, il nome del campo esplicito e la direzione esplicita dell'ordine.
dotancohen,

Risposte:


28

Questa è davvero una brutta cosa fare IMHO, e non è supportato nella maggior parte delle altre piattaforme di database.

I motivi per cui le persone lo fanno:

  • sono pigri - non so perché la gente pensi che la loro produttività sia migliorata scrivendo un codice conciso piuttosto che digitando per altri 40 millisecondi per ottenere un codice molto più letterale.

I motivi sono cattivi:

  • non è auto-documentazione : qualcuno dovrà analizzare l'elenco SELECT per capire il raggruppamento. In realtà sarebbe un po 'più chiaro in SQL Server, che non supporta il cowboy chissà cosa accadrà raggruppamento come fa MySQL.

  • è fragile : qualcuno entra e cambia l'elenco SELEZIONA perché gli utenti aziendali volevano un output di report diverso e ora il tuo output è un casino. Se avessi usato i nomi delle colonne in GROUP BY, l'ordine nell'elenco SELECT sarebbe irrilevante.

SQL Server supporta ORDER BY [ordinale]; ecco alcuni argomenti paralleli contro il suo utilizzo:


9

MySQL ti permette di fare GROUP BYcon gli alias ( Problemi con gli alias di colonna ). Sarebbe molto meglio che fare GROUP BYcon i numeri.

Google ha molti esempi di utilizzo e perché molti hanno smesso di usarlo.

Ad essere sincero con te, non uso i numeri di colonna per ORDER BYe GROUP BYdal 1996 (all'epoca stavo facendo Oracle PL / SQL Development). L'uso dei numeri di colonna è davvero per i vecchi utenti e la compatibilità con le versioni precedenti consente a tali sviluppatori di utilizzare MySQL e altri RDBMS che lo consentono ancora.


8

Si consideri il caso seguente:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Apps         |         1 |
| 2016-05-31 | Applications |         1 |
| 2016-05-31 | Applications |         1 |
| 2016-05-31 | Apps         |         1 |
| 2016-05-31 | Videos       |         1 |
| 2016-05-31 | Videos       |         1 |
| 2016-06-01 | Apps         |         3 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Videos       |         2 |
| 2016-06-01 | Apps         |         2 |
+------------+--------------+-----------+

Devi scoprire il numero di download per servizio al giorno considerando App e applicazioni come lo stesso servizio. Raggruppando per date, servicescomporterebbe AppseApplications essere considerati servizi separati.

In tal caso, la query sarebbe:

 select date, services, sum(downloads) as downloads
 from test.zvijay_test
 group by date,services

E uscita:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Apps         |         2 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Apps         |         5 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

Ma questo non è ciò che desideri poiché le applicazioni e le app da raggruppare sono il requisito. Quindi cosa possiamo fare?

Un modo è quello di sostituire Appscon l' Applicationsuso di CASEun'espressione o della IFfunzione e quindi raggruppandoli su servizi come:

select 
  date,
  if(services='Apps','Applications',services) as services,
  sum(downloads) as downloads
from test.zvijay_test 
group by date,services

Ma questo raggruppa ancora i servizi considerando Appse Applicationscome servizi diversi e fornisce lo stesso output di prima:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Applications |         2 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         4 |
| 2016-06-01 | Applications |         5 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

Il raggruppamento su un numero di colonna consente di raggruppare i dati su una colonna con alias.

select
  date,
  if(services='Apps','Applications',services) as services,
  sum(downloads) as downloads
from test.zvijay_test
group by date,2;

E dandoti così l'output desiderato come di seguito:

+------------+--------------+-----------+
| date       | services     | downloads |
+------------+--------------+-----------+
| 2016-05-31 | Applications |         4 |
| 2016-05-31 | Videos       |         2 |
| 2016-06-01 | Applications |         9 |
| 2016-06-01 | Videos       |         2 |
+------------+--------------+-----------+

Ho letto molte volte che questo è un modo pigro di scrivere query o raggruppare su una colonna con alias non funziona in MySQL, ma questo è il modo di raggruppare su colonne con alias.

Questo non è il modo preferito di scrivere query, usalo solo quando hai davvero bisogno di raggruppare su una colonna con alias.


" Ma questo raggruppa ancora i servizi che considerano app e applicazioni come servizi diversi e fornisce lo stesso risultato di prima ". Questo non sarebbe risolto se avessi scelto un nome diverso (non in conflitto) per l'alias?
Daddy32,

3

Non esiste un motivo valido per usarlo. È semplicemente una scorciatoia pigra appositamente progettata per rendere difficile per alcuni sviluppatori difficili da capire il raggruppamento o l'ordinamento in un secondo momento o per consentire al codice di fallire miseramente quando qualcuno cambia l'ordine delle colonne. Sii rispettoso dei tuoi colleghi sviluppatori e non farlo.


0

Questo ha funzionato per me. Il codice raggruppa le righe fino a 5 gruppi.

SELECT
USR.UID,
USR.PROFILENAME,
(
    CASE 
    WHEN MOD(@curRow, 5) = 0 AND @curRow > 0 THEN
        @curRow := 0
    ELSE
        @curRow := @curRow + 1 
        /*@curRow := 1*/ /*AND @curCode := USR.UID*/
    END
) AS sort_by_total  
FROM
    SS_USR_USERS USR,
    (
        SELECT
            @curRow := 0,
            @curCode := ''
    ) rt
ORDER BY
    USR.PROFILENAME,
    USR.UID

Il risultato sarà il seguente

inserisci qui la descrizione dell'immagine


0
SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2;

SELECT dep_month,dep_day_of_week,dep_date,COUNT(*) AS flight_count FROM flights GROUP BY 1,2,3;

Considerare le query precedenti: Raggruppare per 1 significa raggruppare per la prima colonna e raggruppare per 1,2 significa raggruppare per la prima e seconda colonna e raggruppare per 1,2,3 significa raggruppare per prima seconda e terza colonna. Ad esempio:

raggruppare per 1,2

questa immagine mostra le prime due colonne raggruppate per 1,2, cioè non sta prendendo in considerazione i diversi valori di dep_date per trovare il conteggio (per calcolare il conteggio vengono prese in considerazione tutte le combinazioni distinte delle prime due colonne) mentre la seconda query ne risulta raggruppare per 1,2,3

Immagine. Qui sta prendendo in considerazione tutte le prime tre colonne e là valori diversi per trovare il conteggio cioè, sta raggruppando per tutte le prime tre colonne (per calcolare il conteggio vengono prese in considerazione tutte le combinazioni distinte delle prime tre colonne).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.