这是我的问题(我正在使用SQL Server)
我有一张Students (StudentId, Firstname, Lastname, etc)
的表格。
我有一张记录StudentAttendance (StudentId, ClassDate, etc.)
我记录了其他学生活动(为了简单起见,我在这里概括),例如Papers
表(StudentId, PaperId, etc.)
。可能有零到20篇文章被转入。同样,有一个名为Projects (StudentId, ProjectId, etc.)
的表格。与Papers
相同的交易。
我要做的是为出勤率超过一定水平的学生(比如10个出勤率)创建一个计数清单。像这样:
ID Name Att Paper Proj
123 Baker 23 0 2
234 Charlie 26 5 3
345 Delta 13 3 0
这就是我所拥有的:
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
如果注释掉CountofPaper
和Papers
表的连接(内部或左外部),则查询工作正常。我得到了很多参加过至少10门课程的学生。
然而,如果我加入CountofPapers
和加入,事情会变得疯狂。通过左外连接,任何有论文的学生只会在论文栏中显示他们的出勤人数。通过内部联接,出勤和纸张数量似乎相互多重。
需要指导和赞赏。
戴夫
答案 0 :(得分:1)
看看使用Common Table Expressions,然后划分并征服你的问题。顺便说一句,你在原始查询中偏离1,你将有11个最低限度的注意力
;
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 :(得分:0)
试试这个:
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
答案 2 :(得分:0)
问题是每个学生有多个papers
,因此加入的每一行StudentAttendance
都有Paper
行:每次都会重新添加计数。试试这个:
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的引用的问题
顺便说一句,这不是最快的解决方案,但它是最容易理解的,这是我的意图。您可以通过使用连接到别名选择来避免重新计算,但正如我所说,这是最简单的。