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.


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

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

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.


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

4

CTE zadziałało dla mnie:

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

select COUNT(col1)
from cte;

3

Co powiesz na:

SELECT count(column_1)
FROM
    (SELECT * FROM temptable
    GROUP BY column_1, column_2, column_3, column_4) AS Records

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

1

W PostgreSQL działa to dla mnie:

select count(count.counts) 
from 
    (select count(*) as counts 
     from table 
     group by concept) as count;

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

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


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

-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).


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