2009-03-03 64 views
2

我有一张学生表和一张登记表;一名学生可能有多个可以活动或不活动的登记记录。从可能产生多个记录的连接表中取回单个记录

我想获得一个包含单个学生记录的选择,并指出该学生是否有活动的注册。

我曾想过在内联UDF中使用学生ID来加入注册表,但我想知道是否有更好的方法在单个select语句中执行此操作。

的UDF调用可能看起来像:

Select Student_Name,Student_Email,isEnrolled(Student_ID) from Student 

什么可能的替代方案 - 一个SQL语句 - 是什么样子?

回答

1
select Student_Name, 
     Student_Email, 
     (select count(*) 
     from Enrollment e 
     where e.student_id = s.student_id 
     ) Number_Of_Enrollments 
from Student e 

将获得入学的人数,这应有助于。

+0

如果您有1000名学生,则该声明就像运行1001个查询一样,因为它会分别查询每个学生的入学人数。 – banjollity 2009-03-08 09:43:44

+0

不,这并不坏。数据库可以优化,特别是如果student_id是注册索引的第一部分(我认为这将是)。子查询只需要对注册索引执行索引范围扫描(不需要表本身)。 – 2009-03-16 16:11:08

0

尝试成才这样的:

SELECT Student_Name, Student_Email, CAST((SELECT TOP 1 1 FROM Enrollments e WHERE e.student_id=s.student_id) as bit) as enrolled FROM Student s 

我想你也可以使用存在于SELECT语句,但不积极

1

为什么不加入辅助选择?与其他解决方案不同,这不会为每个返回的行启动子查询,而是一次为所有人收集注册数据。语法可能不完全正确,但您应该明白。

SELECT 
    s.student_name, 
    s.student_email, 
    IsNull(e.enrollment_count, 0) 
FROM 
    Students s 
LEFT OUTER JOIN (
     SELECT 
      student_id, 
      count(*) as enrollment_count 
     FROM 
      enrollments 
     WHERE 
      active = 1 
     GROUP BY 
      student_id 
    ) e 
ON s.student_id = e.student_id 

从注册选择也可以重做一个函数,它返回一个表供您加入。

CREATE FUNCTION getAllEnrollmentsGroupedByStudent() 
RETURNS @enrollments TABLE 
(
    student_id  int, 
    enrollment_count int 
) AS BEGIN 
    INSERT INTO 
     @enrollments 
    (
     student_id, 
     enrollment_count 
    ) SELECT 
     student_id, 
     count(*) as enrollment_count 
    FROM 
     enrollments 
    WHERE 
     active = 1 
    GROUP BY 
     student_id 

    RETURN 
END 


SELECT 
    s.student_name, 
    s.student_email, 
    e.enrollment_count 
FROM 
    Students s 
JOIN 
    dbo.getAllEnrollmentsGroupedByStudent() e 
ON s.student_id = e.student_id 

编辑:
Renze德瓦尔纠正我的坏SQL!

0

尽量避免使用udfs或子查询,它们是性能杀手。 banjolity似乎有一个很好的解决方案,否则,因为它使用derivd表而不是UDF或子查询。

0
select students.name, 
decode(count(1), 0, "no enrollments", "has enrollments") 
    from students, enrollments 
    where 
     students.id = enrollments.sutdent_id and 
     enrollments.is_active = 1 group by students.name 

当然,用您的数据库使用的函数(或case语句)替换解码。