2009-10-01 12 views
113

Mam tabeli uczniów:Jak skutecznie liczyć wystąpienia wartości kolumny w SQL?

id | age 
-------- 
0 | 25 
1 | 25 
2 | 23 

chcę kwerendy dla wszystkich studentów, oraz dodatkową kolumnę, która zlicza ile uczniowie są w tym samym wieku:

id | age | count 
---------------- 
0 | 25 | 2 
1 | 25 | 2 
2 | 23 | 1 

Jaki jest najbardziej wydajny sposób robienia tego? Obawiam się, że pod-zapytanie będzie powolne, i zastanawiam się, czy istnieje lepszy sposób na uzyskanie. Jest tu?

+0

Ponieważ podzapytanie jest statyczne, wystarczy wykonać je tylko raz i można zapisać wynik w tabeli tymczasowej, jak większość z tych odpowiedzi. –

+1

@NickLarsen, tabela temp jest znacznie inna i mniej wydajna niż tabele wyprowadzone (również widoki śródliniowe), których większość odpowiedzi tutaj używa. –

Odpowiedz

166

To powinno działać:

SELECT age, count(age) 
    FROM Students 
GROUP by age 

Jeśli potrzebujesz id jak również można zaliczyć przede jak kwerendy sub tak:

SELECT S.id, S.age, C.cnt 
    FROM Students S 
     INNER JOIN (SELECT age, count(age) as cnt 
        FROM Students 
        GROUP BY age) C ON S.age = C.age 
+1

dla drugiego zapytania, zewnętrzny select powinien być włączony C.cnt, ponieważ nie ma żadnego S.cnt, w przeciwnym razie pojawi się błąd: Niepoprawna nazwa kolumny 'cnt' –

+0

to podanie mi błędu, gdy używam select case_id, count (pgm_code) z pgm grupa według pgm_code; nie wypowiadając grupy według wyrażenia –

3
select s.id, s.age, c.count 
from students s 
inner join (
    select age, count(*) as count 
    from students 
    group by age 
) c on s.age = c.age 
order by id 
6

chciałbym zrobić coś takiego:

select 
A.id, A.age, B.count 
from 
students A, 
(select age, count(*) as count from students group by age) B 
where A.age=B.age; 
19

Jeśli używasz Oracl e, a następnie funkcja o nazwie analytics zrobi lewy. Wygląda to tak:

select id, age, count(*) over (partition by age) from students; 

Jeśli nie używasz Oracle, a następnie trzeba dołączyć z powrotem do hrabiów:

select a.id, a.age, b.age_count 
    from students a 
    join (select age, count(*) as age_count 
      from students 
     group by age) b 
    on a.age = b.age 
+2

+1, pierwsze zapytanie działa dla SQL Server 2005 i wyżej też –

+1

FYI, W SQL Server 2005 drugie zapytanie uruchamia się przy prawie połowie kosztu wykonania (przy użyciu _SET SHOWPLAN_ALL ON_) jako pierwszego. Pomyślałem, że pierwsze byłoby lepsze, ale stara szkoła dołączyła do tego. –

+0

To zadziałało dla mnie - instrukcja partycji ładnie zebrała wartości unikalnie dla mojej kolumny. – theJerm

15

Oto inne rozwiązanie. ten używa bardzo prostej składni. Pierwszym przykładem przyjętego rozwiązania nie działa na starszych wersji Microsoft SQL (czyli 2000)

SELECT age, count(*) 
FROM Students 
GROUP by age 
ORDER BY age 
+1

Bardzo ładne i łatwe rozwiązanie. – schlingel

+0

Jeśli jednak zgrupujesz według wieku, dostaniesz tylko jeden wpis dla wieku 25 lat z liczbą 2 (kiedy rzeczywiście będą potrzebować 2 wpisów z liczbą 2 i oddzielnymi identyfikatorami dla podanego przykładu)? – Ian

+0

Ian, dzięki za informację zwrotną. Czy wykonałeś swoje roszczenie przeciwko DB MS SQL 2000? – Damian

0

i jeśli dane w „wiek” kolumna ma podobne rekordy (czyli wielu ludzi 25 lat, wiele innych są 32 itd.), Powoduje to zamieszanie w dostosowywaniu prawidłowości do każdego ucznia. , aby tego uniknąć, dołączyłem również do tabel na legitymacji studenckiej.

Powiązane problemy