Policz liczbę rekordów zwróconych przez grupę

138

Jak policzyć liczbę rekordów zwróconych przez grupę według zapytania,

Na przykład:

select count(*) 
from temptable
group by column_1, column_2, column_3, column_4

Daje mi,

1
1
2

Muszę policzyć powyższe rekordy, aby uzyskać 1 + 1 + 1 = 3.

Chris
źródło
3
@LorenVS: Ale to dałoby mi liczbę rekordów w tabeli. Potrzebuję liczby rekordów po zakończeniu grupy.
Chris,
3
Jednak grupowanie według nie zmienia liczby wierszy. 1 + 1 + 2 (w twoim przykładzie) będzie liczbą wierszy w tabeli. Szukasz 3? Liczba różnych grup?
LorenVS
2
Inny sposób sformułowania pytania: jak wybrać liczbę różnych poziomów grupowania dla danego zapytania?
Julian
Nie zawsze jest oczywiste, dlaczego użytkownik zadaje pytanie, ale dotarłem tutaj, ponieważ sprawdzam, czy kolumna w widoku jest kandydującym kluczem podstawowym lub kombinacją. „select count (different COLUMNNAME) from VIEWNAME” przekracza limit czasu, gdzie grupowanie według działa, jeśli mogę uzyskać sumę.
Ken Forslund

Odpowiedzi:

169

Możesz zrobić oba w jednym zapytaniu, używając klauzuli OVER na innym COUNT

select
    count(*) RecordsPerGroup,
    COUNT(*) OVER () AS TotalRecords
from temptable
group by column_1, column_2, column_3, column_4
gbn
źródło
Wiem, że jest to pytanie dotyczące SQL Server, ale dla odniesienia: To nie działa na DB / 2 (w moim przypadku na IBM iSeries). Zobacz mój komentarz w odpowiedzi
Thomasa
Jak bym powtórzył tę policzoną liczbę?
McDan Garrett
1
Wadą tego rozwiązania jest to, że daje ono odpowiedź wiele razy (dla każdej kombinacji column_1, column_2, column_3, column_4). Może to być znaczący efekt uboczny lub nie, w zależności od sposobu przetwarzania wyników.
cartbeforehorse
3
Aby zwrócić tylko liczbę rekordów, dodaj wybraną liczbę górną (1) licznika (*) do () jako ....
Guilherme Campos Hazan
2
W moim przypadku użycie TOP (1) COUNT ( ) OVER () miało słabą wydajność zapytania. Ponieważ potrzebowałem tylko liczby grup, zmieniłem to na DISTINCT COUNT ( ) OVER (), a wydajność zapytania znacznie się poprawiła.
Joe Aldrich
71

Najprostszym rozwiązaniem jest użycie tabeli pochodnej:

Select Count(*)
From    (
        Select ...
        From TempTable
        Group By column_1, column_2, column_3, column_4
        ) As Z

Innym rozwiązaniem jest użycie Count Distinct:

Select ...
    , ( Select Count( Distinct column_1, column_2, column_3, column_4 )
        From TempTable ) As CountOfItems
From TempTable
Group By column_1, column_2, column_3, column_4
Tomasz
źródło
Pierwsza odpowiedź działa również na DB / 2, ale z jakiegoś powodu wymaga dodania AS TMP do działania (jak dodano troutinator)
Bjinse
5
@Bjinse - Niektóre DBMS wymagają, aby wszystkie tabele pochodne miały alias. Wszyscy to zaakceptują, więc włączenie go nie zaszkodzi. Dodam to do mojej odpowiedzi.
Thomas
25

Wiem, że jest dość późno, ale nikt tego nie zasugerował:

select count ( distinct column_1, column_2, column_3, column_4) 
from   temptable

Działa to przynajmniej w Oracle - obecnie nie mam innych baz danych do przetestowania i nie jestem zbyt zaznajomiony ze składnią T-Sql i MySQL.

Nie jestem też do końca pewien, czy bardziej wydajne jest to w parserze, aby zrobić to w ten sposób, czy też rozwiązanie zagnieżdżania instrukcji select dla wszystkich innych jest lepsze. Ale uważam, że ten jest bardziej elegancki z punktu widzenia kodowania.

cartbeforehorse
źródło
Thomas dodał Twoje rozwiązanie do swojej odpowiedzi. Tak czy siak. Nie polecałbym tego nigdy robić ze względów konserwacyjnych, inne rozwiązania są znacznie przyjemniejsze.
Răzvan Flavius ​​Panda
@ RăzvanFlaviusPanda 1. Dlaczego? Co jest ładniejszego w innych rozwiązaniach? Zagnieżdżanie SQL jest bardziej rozwlekłe i dla mnie bardziej chaotyczne i trudniejsze do zrozumienia (czyli trudniejsze do utrzymania w sensie wsparcia). Rozumiem, że możesz preferować inne sposoby, ale to nie jest powód, aby go „polecać” zamiast czyichś preferencji. Thomas wysunął podobną sugestię, tak, ale ponownie sprawia, że ​​wygląda na to, że zagnieżdżanie kodu SQL jest niezbędną częścią rozwiązania, a tak nie jest.
cartbeforehorse
12

Próbowałem osiągnąć to samo bez podzapytania i udało mi się uzyskać wymagany wynik, jak poniżej

SELECT DISTINCT COUNT(*) OVER () AS TotalRecords
FROM temptable
GROUP BY column_1, column_2, column_3, column_4
Manish Mulani
źródło
4

CTE zadziałało dla mnie:

with cte as (
  select 1 col1
  from temptable
  group by column_1
)

select COUNT(col1)
from cte;
SQL Pete
źródło
3

Co powiesz na:

SELECT count(column_1)
FROM
    (SELECT * FROM temptable
    GROUP BY column_1, column_2, column_3, column_4) AS Records
PedroC88
źródło
1

Mógłbyś:

select sum(counts) total_records from (
    select count(*) as counts
    from temptable
    group by column_1, column_2, column_3, column_4
) as tmp
troutinator
źródło
1

W PostgreSQL działa to dla mnie:

select count(count.counts) 
from 
    (select count(*) as counts 
     from table 
     group by concept) as count;
omar
źródło
1

Czy możesz wykonać poniższy kod? To działało w Oracle.

SELECT COUNT(COUNT(*))
FROM temptable
GROUP BY column_1, column_2, column_3, column_4
Arif
źródło
1
Nie można uruchomić agregacji w agregacie na serwerze sql.
A. Greensmith
0

Możesz również uzyskać poniższe zapytanie

select column_group_by,count(*) as Coulm_name_to_be_displayed from Table group by Column;

-- For example:
select city,count(*) AS Count from people group by city
Nitish Sahoo
źródło
0

Spróbuj tego zapytania:

select top 1 TotalRows = count(*) over () 
from yourTable
group by column1, column2
Marimuthu Shanmugasundaram
źródło
0

Poniżej dla PrestoDb , gdzie FirstField może mieć wiele wartości:

select *
            , concat(cast(cast((ThirdTable.Total_Records_in_Group * 100 / ThirdTable.Total_Records_in_baseTable) as DECIMAL(5,2)) as varchar), '%') PERCENTage
from 
(
    SELECT FirstTable.FirstField, FirstTable.SecondField, SecondTable.Total_Records_in_baseTable, count(*) Total_Records_in_Group
    FROM BaseTable FirstTable
    JOIN (
            SELECT FK1, count(*) AS Total_Records_in_baseTable 
            FROM BaseTable
            GROUP BY FK1
        ) SecondTable
    ON FirstTable.FirstField = SecondTable.FK1
    GROUP BY FirstTable.FirstField, FirstTable.SecondField, SecondTable.Total_Records_in_baseTable
    ORDER BY FirstTable.FirstField, FirstTable.SecondField
) ThirdTable
SUKUMAR S
źródło
-1

Co powiesz na użycie funkcji partycjonowania COUNT OVER (PARTITION BY {column to group by}) w SQL Server?

Na przykład, jeśli chcesz pogrupować sprzedaż produktów według ItemID i chcesz zliczać każdy odrębny ItemID, po prostu użyj:

SELECT
{columns you want} ,
COUNT(ItemID) OVER (PARTITION BY ItemID) as BandedItemCount ,
{more columns you want}... ,
FROM {MyTable}

Jeśli zastosujesz to podejście, możesz pozostawić GROUP BY poza obrazem - zakładając, że chcesz zwrócić całą listę (tak jak możesz zgłosić pasmowanie, w którym musisz znać całą liczbę elementów, które zamierzasz połączyć, bez konieczności posiadania wyświetlić cały zestaw danych, czyli usługi Reporting Services).

Johnny B.
źródło
Jaka będzie BandedItemCountdokładnie wartość ? Czy różni się między wierszami wyjściowymi? Pytający szuka liczby różnych poziomów grupowania.
Julian