Come usare il conteggio e il raggruppamento nella stessa istruzione select


223

Ho una query di selezione sql che ha un gruppo da. Voglio contare tutti i record dopo il gruppo per dichiarazione. C'è un modo per questo direttamente da sql? Ad esempio, avendo una tabella con gli utenti voglio selezionare le diverse città e il numero totale di utenti

select town, count(*) from user
group by town

Voglio avere una colonna con tutte le città e un'altra con il numero di utenti in tutte le righe.

Un esempio del risultato per avere 3 città e 58 utenti in totale è:

Town         Count
Copenhagen   58
NewYork      58
Athens       58

vuoi dire che vuoi che il tuo set di risultati abbia 2 conteggi uno per le città e uno per gli utenti?
Leslie,

2
Quindi vuoi una riga per ogni città e in ogni riga, la colonna 2 contiene il conteggio totale di tutti gli utenti? Quindi la colonna 2 ha lo stesso valore per ogni riga? Se modifichi per includere dati di esempio e l'output richiesto, saremo in grado di fornirti esattamente quello che desideri.
AakashM,

Hai ragione AakashM! L'ho appena modificato.
Stavros,


1
Avvertenza per i lettori: la maggior parte delle risposte non riesce a fornire una risposta alla query aggiornata.
Rick James,

Risposte:


271

Questo farà quello che vuoi (elenco delle città, con il numero di utenti in ciascuna):

select town, count(town) 
from user
group by town

È possibile utilizzare la maggior parte delle funzioni di aggregazione durante l'utilizzo GROUP BY.

Aggiornamento (in seguito alla modifica di domande e commenti)

È possibile dichiarare una variabile per il numero di utenti e impostarlo sul numero di utenti, quindi selezionare con quello.

DECLARE @numOfUsers INT
SET @numOfUsers = SELECT COUNT(*) FROM user

SELECT DISTINCT town, @numOfUsers
FROM user

questo è esattamente ciò che l'OP ha scritto? nvm, vedo la tua differenza, non stai contando Town * *
Leslie,

@Leslie - non c'è differenza tra le due query. Restituiranno lo stesso set di risultati. Non mi piace l'uso di *... L'OP ha risposto alla sua domanda, ma non sembrava nemmeno provarlo, sto solo confermando che è corretto :) fredosaurus.com/notes-db/select/groupby.html
Oded

Ancora una volta non quello che speravo, ma sembra che questa sia la soluzione migliore ..;) Grazie
Stavros,

149

Puoi usare COUNT(DISTINCT ...):

SELECT COUNT(DISTINCT town) 
FROM user

3
funziona come un incanto ... dovrebbe essere scelta la risposta principale .. tranne qualche indagine che non va bene.
Victor,

2
Penso che significhino se inserisci COUNT (città DISTINCT) nella clausola WHERE. Questo perché è una funzione aggregata e deve essere fornita nella clausola HAVING. Questa query SQL è fuorviante per alcuni quando SELECT COUNT (città DISTINCT) si trasforma in un GROUP BY implicito, a causa sia delle parole chiave COUNT che DISTINCT, ciascuna parola da sola si raggrupperebbe implicitamente.
A. Greensmith,

Grazie. Upvote. Esattamente ciò che è necessario: raggruppa + conta in una sola operazione e ottieni una singola riga nel risultato.
Green,

Merda .. Non sapevo che fosse possibile!
Hugo S. Mendes

1
@milkovsky - No, non è necessario eliminarlo. Trovo irritante che questa domanda e le molte risposte si siano biforcate nel risolvere due diversi problemi. La tua risposta devia in due modi: nessuna towncolonna, ed è COUNTsla cosa sbagliata (città invece che utente).
Rick James,

37

L'altro modo è:

/* Number of rows in a derived table called d1. */
select count(*) from
(
  /* Number of times each town appears in user. */
  select town, count(*)
  from user
  group by town
) d1

5
ha bisogno di alias altrimenti non funzionerebbe in mysql. seleziona count (*) da () agr
amas

4

Con Oracle è possibile utilizzare le funzioni analitiche:

select town, count(town), sum(count(town)) over () total_count from user
group by town

Le altre tue opzioni sono usare una sottoquery:

select town, count(town), (select count(town) from user) as total_count from user
group by town

qualcosa come l'ultimo avrebbe funzionato, ma volevo vedere se c'è qualche altra soluzione ..
Stavros,

E non puoi usare la prima opzione (funzione analitica)? Quale piattaforma di database stai usando?
Tommi,

@Stavros: l'ultimo è lento
Michael Buen

4

Se vuoi ordinare in base al conteggio (sembra semplice ma non riesco a trovare una risposta nello stack di come farlo) puoi fare:

        SELECT town, count(town) as total FROM user
        GROUP BY town ORDER BY total DESC

4

Dieci risposte non cancellate; la maggior parte non fa ciò che l'utente ha richiesto. La maggior parte delle risposte ha letto male la domanda pensando che ci siano 58 utenti in ogni città invece di 58 in totale. Anche i pochi corretti non sono ottimali.

mysql> flush status;
Query OK, 0 rows affected (0.00 sec)

SELECT  province, total_cities
    FROM       ( SELECT  DISTINCT province  FROM  canada ) AS provinces
    CROSS JOIN ( SELECT  COUNT(*) total_cities  FROM  canada ) AS tot;
+---------------------------+--------------+
| province                  | total_cities |
+---------------------------+--------------+
| Alberta                   |         5484 |
| British Columbia          |         5484 |
| Manitoba                  |         5484 |
| New Brunswick             |         5484 |
| Newfoundland and Labrador |         5484 |
| Northwest Territories     |         5484 |
| Nova Scotia               |         5484 |
| Nunavut                   |         5484 |
| Ontario                   |         5484 |
| Prince Edward Island      |         5484 |
| Quebec                    |         5484 |
| Saskatchewan              |         5484 |
| Yukon                     |         5484 |
+---------------------------+--------------+
13 rows in set (0.01 sec)

SHOW session status LIKE 'Handler%';

+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Handler_commit             | 1     |
| Handler_delete             | 0     |
| Handler_discover           | 0     |
| Handler_external_lock      | 4     |
| Handler_mrr_init           | 0     |
| Handler_prepare            | 0     |
| Handler_read_first         | 3     |
| Handler_read_key           | 16    |
| Handler_read_last          | 1     |
| Handler_read_next          | 5484  |  -- One table scan to get COUNT(*)
| Handler_read_prev          | 0     |
| Handler_read_rnd           | 0     |
| Handler_read_rnd_next      | 15    |
| Handler_rollback           | 0     |
| Handler_savepoint          | 0     |
| Handler_savepoint_rollback | 0     |
| Handler_update             | 0     |
| Handler_write              | 14    |  -- leapfrog through index to find provinces  
+----------------------------+-------+

Nel contesto del PO:

SELECT  town, total_users
    FROM       ( SELECT  DISTINCT town  FROM  canada ) AS towns
    CROSS JOIN ( SELECT  COUNT(*) total_users  FROM  canada ) AS tot;

Dal momento che c'è solo una riga da tot, ilCROSS JOIN non è così voluminoso come potrebbe essere altrimenti.

Il solito schema è COUNT(*)invece di COUNT(town). Quest'ultimo implica verificare townche non sia nullo, il che non è necessario in questo contesto.


2

Puoi usare DISTINCT all'interno del CONTE come quello che ha detto milkovsky

nel mio caso:

select COUNT(distinct user_id) from answers_votes where answer_id in (694,695);

In questo modo il conteggio dei voti delle risposte viene considerato lo stesso user_id di un conteggio


2

So che questo è un vecchio post, in SQL Server:

select  isnull(town,'TOTAL') Town, count(*) cnt
from    user
group by town WITH ROLLUP

Town         cnt
Copenhagen   58
NewYork      58
Athens       58
TOTAL        174

5
Non c'è niente di sbagliato nel rispondere ai vecchi post. Tuttavia, includi una spiegazione del tuo codice e del codice stesso.
Shelvacu,

L'equivalente MySQL ( IFNULLinvece di ISNULL) porta a numeri diversi per ogni città; l'utente voleva il totale. Secondo la domanda, 58, non 174, è il totale.
Rick James,

1

Se si desidera selezionare la città e il conteggio totale degli utenti, è possibile utilizzare questa query di seguito:

SELECT Town, (SELECT Count(*) FROM User) `Count` FROM user GROUP BY Town;

Questo presuppone (forse ragionevolmente) che non ci siano "utenti" duplicati in User.
Rick James,

1

se si desidera utilizzare l'opzione Seleziona tutte le query con conteggio, provare questo ...

 select a.*, (Select count(b.name) from table_name as b where Condition) as totCount from table_name  as a where where Condition

Grazie per questo frammento di codice, che potrebbe fornire un aiuto limitato e immediato. Una spiegazione adeguata migliorerebbe notevolmente il suo valore a lungo termine mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con altre domande simili. Si prega di modificare la risposta di aggiungere qualche spiegazione, tra le ipotesi che hai fatto.
Toby Speight,

0

Prova il seguente codice:

select ccode, count(empno) 
from company_details 
group by ccode;

usiamo questo codice per trovare quanti impiegati totali per il calcolo attuale in ogni singolo esempio di codice (codice azienda): count (empno) è 1839 per ccode 1 e count (empno) è 9421 per ccode 47.
balajibran
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.