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

1
«присоединиться к старой школе побить это» просто потому, что ОБЩАЯ СЧЕТЧИК СТРОКИ будет обрабатываться иначе. Во втором запросе есть встроенная группировка, которая потенциально значительно уменьшает количество строк. Попробуйте добавить DISTINCT к первому запросу: «выберите DISTINCT id, age, count (*) over (разбиение по возрасту) из студентов» - это должно быть сопоставимо
— 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.