Jak korzystać z liczenia i grupowania według tej samej instrukcji select


223

Mam zapytanie SQL sql, które ma grupę według. Chcę policzyć wszystkie rekordy po grupie według instrukcji. Czy jest na to sposób bezpośrednio z sql? Na przykład, mając tabelę z użytkownikami, chcę wybrać różne miasta i całkowitą liczbę użytkowników

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

Chcę mieć kolumnę ze wszystkimi miastami i kolejną z liczbą użytkowników we wszystkich wierszach.

Przykładem wyniku posiadania 3 miast i 58 użytkowników jest:

Town         Count
Copenhagen   58
NewYork      58
Athens       58

masz na myśli, że chcesz, aby zestaw wyników zawierał 2 liczby dla miasta i jedną dla użytkowników?
Leslie,

2
Czy chcesz mieć jeden wiersz dla każdego miasta, a w każdym wierszu kolumna 2 zawiera całkowitą liczbę wszystkich użytkowników? Więc kolumna 2 ma taką samą wartość dla każdego wiersza? Jeśli edytujesz, aby uwzględnić przykładowe dane i wymagane dane wyjściowe, będziemy mogli dać ci dokładnie to, czego chcesz.
AakashM

Masz rację AakashM! Właśnie to zredagowałem.
Stavros


1
Zastrzeżenie dla czytelników: większość odpowiedzi nie zawiera odpowiedzi na zapytanie w formie zaktualizowanej.
Rick James

Odpowiedzi:


271

To zrobi, co chcesz (lista miast, z liczbą użytkowników w każdym):

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

Można korzystać z większości funkcji agregujących podczas używania GROUP BY.

Aktualizacja (po zmianie pytania i komentarze)

Możesz zadeklarować zmienną dla liczby użytkowników i ustawić ją na liczbę użytkowników, a następnie wybrać ją.

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

SELECT DISTINCT town, @numOfUsers
FROM user

dokładnie to napisał OP? nvm, widzę różnicę, liczysz Town not * *
Leslie,

@ Leslie - nie ma różnicy między tymi dwoma zapytaniami. Zwrócą ten sam zestaw wyników. Po prostu nie podoba mi się użycie *... OP odpowiedział na swoje pytanie, ale zdawało się, że nawet go nie przetestował, po prostu potwierdzam, że jest poprawne :) fredosaurus.com/notes-db/select/groupby.html
Oded

Znowu nie to, na co liczyłem, ale wydaje się, że to najlepsze rozwiązanie ..;) Dzięki
Stavros

149

Możesz użyć COUNT(DISTINCT ...):

SELECT COUNT(DISTINCT town) 
FROM user

3
działa jak urok ... należy wybrać główną odpowiedź .. z wyjątkiem niektórych prób, że to nie jest dobre.
Victor

2
Myślę, że mają na myśli, jeśli umieścisz COUNT (miasto DISTINCT) w klauzuli WHERE. Jest tak, ponieważ jest to funkcja agregująca i należy ją podać w klauzuli HAVING. To zapytanie SQL jest mylące dla niektórych, ponieważ SELECT COUNT (miasto DISTINCT) zamienia się w niejawną grupę GROUP BY, zarówno ze względu na COUNT, jak i DISTINCT słowa kluczowe, każde słowo kluczowe osobno również pośrednio pogrupuje.
A. Greensmith

Dzięki. Głosuj. Dokładnie to, co jest potrzebne - grupa + liczyć w jednym op i uzyskać wynik w jednym wierszu.
Green

Cholera .. Nie wiedziałem, że to możliwe!
Hugo S. Mendes

1
@milkovsky - Nie, nie musisz go usuwać. Po prostu uważam za irytację, że to pytanie i wiele odpowiedzi rozwikłały się w rozwiązywaniu dwóch różnych problemów. Twoja odpowiedź różni się na dwa sposoby - bez townkolumny i jest COUNTszła rzecz (miasto zamiast użytkownika).
Rick James

37

Drugi sposób to:

/* 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
potrzebuje aliasu, inaczej nie działałby w mysql. wybierz count (*) from () agr
amas

4

Dzięki Oracle możesz korzystać z funkcji analitycznych:

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

Inne opcje to użycie podzapytania:

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

coś takiego jak ostatni zadziałałoby, ale chciałem sprawdzić, czy jest jakieś inne rozwiązanie ..
Stavros

I nie możesz użyć pierwszej opcji (funkcja analityczna)? Z jakiej platformy bazy danych korzystasz?
Tommi

@Stavros: Ostatni jest wolny
Michael Buen

4

Jeśli chcesz zamówić według liczby (brzmi prosto, ale nie mogę znaleźć odpowiedzi na stosie, jak to zrobić), możesz:

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

4

Dziesięć nieodebranych odpowiedzi; większość nie robi tego, o co prosi użytkownik. Większość odpowiedzi błędnie odczytuje pytanie, ponieważ uważa, że ​​w każdym mieście jest 58 użytkowników zamiast 58 ogółem. Nawet kilka poprawnych nie jest optymalnych.

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  
+----------------------------+-------+

W kontekście PO:

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

Ponieważ jest tylko jeden wiersz tot, CROSS JOINnie jest tak obszerny, jak mógłby być.

Zwykłym wzorem jest COUNT(*)zamiast COUNT(town). To ostatnie oznacza sprawdzanie, czy townnie ma wartości zerowej, co w tym kontekście nie jest konieczne.


2

Możesz użyć DISTINCT wewnątrz COUNT, tak jak powiedział Milkovsky

w moim przypadku:

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

Spowoduje to zwiększenie liczby głosów odpowiedzi uznawanych za ten sam identyfikator_użytkownika, co jedna liczba


2

Wiem, że to stary post w 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
Nie ma nic złego w odpowiadaniu na stare posty. Dołącz jednak wyjaśnienie swojego kodu, a także sam kod.
Shelvacu,

Odpowiednik MySQL ( IFNULLzamiast ISNULL) prowadzi do różnych liczb dla każdego miasta; użytkownik chciał sumy. Zgodnie z pytaniem 58, a nie 174, to suma.
Rick James

1

Jeśli chcesz wybrać miasto i całkowitą liczbę użytkowników, możesz użyć tego zapytania poniżej:

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

Zakłada się (być może rozsądnie), że nie ma duplikatów „użytkowników” w User.
Rick James

1

jeśli chcesz użyć opcji Wybierz wszystkie zapytania z liczbą, spróbuj tego ...

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

Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną, natychmiastową pomoc. Właściwe wyjaśnienie znacznie poprawiłoby jego długoterminową wartość, pokazując, dlaczego jest to dobre rozwiązanie problemu i uczyniłoby to bardziej użytecznym dla przyszłych czytelników z innymi podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
Toby Speight,

0

Wypróbuj następujący kod:

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

używamy tego kodu, aby sprawdzić, ilu pracowników ogółem dla każdego dnia oblicza w każdym kodzie (kod firmy) przykład: liczba (empno) wynosi 1839 dla kodu 1, a liczba (empno) wynosi 9421 dla kodu 47.
balajibran
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.