首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SQL -从多个表中选择计数

SQL -从多个表中选择计数
EN

Stack Overflow用户
提问于 2011-06-24 11:30:37
回答 3查看 2.9K关注 0票数 2

这是我的问题(我使用的是SQL Server)

我有一桌Students (StudentId, Firstname, Lastname, etc)

我有一个记录StudentAttendance (StudentId, ClassDate, etc.)的表

我记录其他学生活动(为了简单起见,我在这里泛化一下),比如Papers(StudentId, PaperId, etc.)。可能会有0到20篇论文上交。类似地,有一个名为Projects (StudentId, ProjectId, etc.)的表。与Papers的交易相同。

我要做的是为出勤率超过一定水平(比如10次出勤率)的学生创建一个计数列表。如下所示:

代码语言:javascript
复制
ID    Name      Att    Paper Proj
123   Baker     23     0     2
234   Charlie   26     5     3
345   Delta     13     3     0

这就是我所拥有的:

代码语言:javascript
复制
select 
  s.StudentId,
  s.Lastname,
  COUNT(sa.StudentId) as CountofAttendance,
  COUNT(p.StudentId) as CountofPapers
from Student s
inner join StudentAttendance sa on (s.StudentId = sa.StudentId)
left outer join Paper p on (s.StudentId = p.StudentId)
group by s.StudentId, s.Lastname
Having COUNT(sa.StudentId) > 10
order by CountofAttendance

如果注释掉了Papers表的CountofPaper和连接(内部或外部),查询就能正常工作。我得到了至少上过10节课的学生的数量。

但是,如果我放入CountofPapers和join,事情就会变得疯狂。使用左外部连接,任何有论文的学生只在论文列中显示他们的出席率。使用内部连接时,出席率和论文数量似乎都会相互影响。

需要并感谢您的指导。

戴夫

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-06-24 11:36:16

问题是每个学生有多个papers,所以连接的每一行Paper都有一个StudentAttendance行:每次都会重新添加计数。试试这个:

代码语言:javascript
复制
select 
  s.StudentId,
  s.Lastname,
  (select COUNT(*) from StudentAttendance where s.StudentId = sa.StudentId) as CountofAttendance,
  (select COUNT(*) from Paper where s.StudentId = p.StudentId) as CountofPapers
from Student s
where (select COUNT(*) from StudentAttendance where s.StudentId = sa.StudentId) > 10
order by CountofAttendance

进行了编辑,以纳入参考CountofAttendance的问题

顺便说一句,这不是最快的解决方案,但它是最容易理解的,这是我的意图。您可以通过对带有别名的select使用联接来避免重新计算,但正如我所说的,这是最简单的。

票数 0
EN

Stack Overflow用户

发布于 2011-06-24 11:47:11

看看如何使用Common Table Expressions,然后分开解决你的问题。顺便说一句,您在原始查询中差了1,最低出席率为11

代码语言:javascript
复制
;
WITH GOOD_STUDENTS AS
(
-- this query defines all students with 10+ attendance
SELECT
    S.StudentID
,   count(1) AS attendence_count
FROM
    Student S
    inner join 
    StudentAttendance sa 
    on (s.StudentId = sa.StudentId)
GROUP BY
    S.StudentId
HAVING
    COUNT(1) >= 10
)
,  STUDIOUS_STUDENTS AS
(
-- lather, rinse, repeat for other metrics
SELECT
    S.StudentID
,   count(1) AS paper_count
FROM
    Student S
    inner join 
    Papers P 
    on (s.StudentId = P.StudentId)
GROUP BY
    S.StudentId
)
,  GREGARIOUS_STUDENTS AS
(
SELECT
    S.StudentID
,   count(1) AS project_count
FROM
    Student S
    inner join 
    Projects P 
    on (s.StudentId = P.StudentId)
GROUP BY
    S.StudentId
)
-- And now we roll it all together
SELECT
    S.*
,   G.attendance_count
,   SS.paper_count
,   GS.project_count
-- ad nauseum
FROM
    -- back to the well on this one as there may be 
    -- students did nothing
    Students S
    LEFT OUTER JOIN
        GOOD_STUDENTS G
        ON G.studentId = S.studentId
    LEFT OUTER JOIN
        STUDIOUS_STUDENTS SS
        ON SS.studentId = S.studentId
    LEFT OUTER JOIN
        GREGARIOUS_STUDENTS GS
        ON GS.studentId = S.studentId

我看到了很多其他的答案,但我打了太长时间才放弃;)

票数 1
EN

Stack Overflow用户

发布于 2011-06-24 11:35:54

试试这个:

代码语言:javascript
复制
select std.StudentId, std.Lastname, att.AttCount, pap.PaperCount, prj.ProjCount
from Students std
    left join
    (
        select StudentId, count(*) AttCount
        from StudentAttendance
    ) att on
        std.StudentId = att.StudentId
    left join
    (
        select StudentId, count(*) PaperCount
        from Papers
    ) pap on
        std.StudentId = pap.StudentId
    left join
    (
        select StudentId, count(*) ProjCount
        from Projects
    ) prj on
        std.StudentId = prj.StudentId
where att.AttCount > 10
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6463024

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档