如何在SQL中有效地计算列值的出现?


166

我有一张学生桌:

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

我想查询所有学生,并增加一列来统计有多少学生年龄相同:

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

最有效的方法是什么?我担心子查询会很慢,我想知道是否有更好的方法。在那儿?

Answers:


255

这应该工作:

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

如果还需要ID,则可以将上述内容作为子查询包括在内,如下所示:

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
当我使用pgm_code的pgm组中的select case_id,count(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)。我以为第一个会更好,但是老派的加入击败了它。
KM。

1
“老派参加击败了它”仅仅是因为要处理的总行数不同。在第二个查询中,有一个嵌入式的分组依据,有可能极大地减少行数。尝试在第一个查询中添加DISTINCT:“从学生中选择DISTINCT id,年龄,count(*)超过(按年龄划分)” –应该具有可比性
quetzalcoatl

19

这是另一个解决方案。这使用非常简单的语法。公认的解决方案的第一个示例不适用于旧版本的Microsoft SQL(例如2000)

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

1
但是,如果按年龄分组,则25岁时只能获得1个计数为2的条目(当他们实际上想要2个计数为2的条目且给出的示例具有单独的ID时)?
伊恩

1
伊恩,感谢您的反馈。您是否针对MS SQL 2000 DB执行了索赔?
Damian

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*
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.