Як ефективно підрахувати виникнення значення стовпця в SQL?


166

У мене є таблиця студентів:

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

Я хочу запитати всіх студентів та додатковий стовпець, який підраховує кількість учнів одного віку:

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

Який найефективніший спосіб зробити це? Я боюся, що підзапит буде повільним, і мені цікаво, чи є кращий спосіб . Є там?

Відповіді:


256

Це має працювати:

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

Якщо вам також потрібен ідентифікатор, ви можете включити вищезазначене як підзапит, як-от так:

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

2
для другого запиту зовнішній вибір повинен бути на C.cnt, оскільки немає S.cnt, інакше ви отримаєте помилку: Неправильна назва стовпця 'cnt'
KM.

1
його помилка надання для мене, коли я використовую select case_id, count (pgm_code) з групи pgm по pgm_code; це говорить не група за виразом
Rishabh Agarwal

26

Якщо ви використовуєте Oracle, то функція, яка називається аналітика, зробить свою справу. Це виглядає приблизно так:

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

Якщо ви не використовуєте Oracle, вам потрібно буде приєднатися до рахунків:

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
FYI, на SQL Server 2005 другий запит працює майже з половиною вартості виконання (використовуючи SET SHOWPLAN_ALL ON ) як перший. Я думав, що перше було б краще, але стара школа приєдналася.
КМ.

1
"приєднайтесь до старої школи, переможете її" просто тому, що ОБРАЗУВАТИ РОЗМІРУВАННЯ РОЗШИРЕНЬ, яка обробляється. У другому запиті є вбудована група-by, яка потенційно значно зменшує кількість рядків. Спробуйте додати DISTINCT до першого запиту: "виберіть ідентифікатор DISTINCT, вік, кількість (*) більше (розділ за віком) у студентів" - це має бути порівняно
quetzalcoatl

19

Ось ще одне рішення. у цьому використовується дуже простий синтаксис. Перший приклад прийнятого рішення не працював на старих версіях Microsoft SQL (тобто 2000 р.)

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

1
Якщо ви згрупуєтесь за віком, ви отримаєте лише один запис для 25 років з рахунком 2 (коли вони насправді хочуть 2 записи з кількістю 2 та окремі ідентифікатори для наведеного прикладу)?
Ян

1
Ян, дякую за відгуки. Чи виконували ви претензію щодо бази даних MS SQL 2000?
Даміан

7

Я б робив щось на кшталт:

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;

4
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

1

і якщо дані у стовпці "вік" мають подібні записи (тобто багатьом людям 25 років, багатьом іншим - 32 і так далі), це створює плутанину в вирівнюванні кількості підрахунків кожного учня. щоб уникнути цього, я приєднався до таблиць ідентифікатора студента.

SELECT S.id, S.age, C.cnt
FROM Students S 
INNER JOIN (SELECT id, age, count(age) as cnt  FROM Students GROUP BY student,age) 
C ON S.age = C.age *AND S.id = C.id*
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.