如何在WHERE子句的SELECT子句中使用子查询的输出?

时间:2016-01-12 15:54:57

标签: sql-server performance optimization subquery

这是关于SQL Server 2005的。 如何在SELECT子句中的WHERE子句中使用子查询的输出?

Student_Master

Student_Id  Student_Name    
1           A
2           B
3           C

Student_Details

Student_Id  Student_Info
1           1_Info1
2           2_Info1
2           2_Info2
2           2_Info3

我想从表Student_Master和COUNT(Student_Details.Student_Info)获取所有列,其中学生信息计数> 0

预期产出: -

Student_Id  Student_Name    InfoCount
1           A               1
2           B               3

以下是INCORRECT语法,但要解释我想要做的事情: -

SELECT Student_Id, Student_Name, 
(
  SELECT COUNT(*) FROM Student_Details
  WHERE Student_Master.Student_Id = Student_Details.Student_Id
) AS InfoCount
FROM Student_Master
WHERE InfoCount > 0

我知道以下CORRECT语法有效: -

SELECT Student_Id, Student_Name, 
(
  SELECT COUNT(*) FROM Student_Details
  WHERE Student_Master.Student_Id = Student_Details.Student_Id
) AS InfoCount
FROM Student_Master
WHERE (
  SELECT COUNT(*) FROM Student_Details
  WHERE Student_Master.Student_Id = Student_Details.Student_Id
)> 0

但是在这里,我必须写两次相同的子查询。这个子查询将执行两次,并且会达到性能。主表有2500万条记录,详细信息表有1亿条记录。

索引和其他优化都可以,但我想首先编写最优化的查询。

2 个答案:

答案 0 :(得分:3)

如果您只是内部加入 Student_MasterStudent_Details,您只会获得包含count > 0

的记录
SELECT  Student_Id,
        Student_Name,
        COUNT(*) InfoCount
FROM    Student_Master sm
        JOIN Student_Details sd ON sm.Student_Id = sd.Student_Id
GROUP BY Student_Id,
        Student_Name

如果出于某种原因需要查找计数大于1的记录,那么您将使用分组

SELECT  Student_Id,
        Student_Name,
        COUNT(*) InfoCount
FROM    Student_Master sm
        JOIN Student_Details sd ON sm.Student_Id = sd.Student_Id
GROUP BY Student_Id,
        Student_Name
HAVING  COUNT(*) > 1

如果你想避免使用大型的Group by语句,你可以在这里内部加入一个子查询。

SELECT  sm.Student_Id,
        sm.Student_Name,
        ic.InfoCount
FROM    Student_Master sm
        INNER JOIN (
                SELECT  Student_Id, COUNT(*) InfoCount
                FROM    Student_Details 
                GROUP BY Student_Id 
            ) ic ON sm.Student_Id = ic.Student_Id

答案 1 :(得分:1)

最简单的方法,使用APPLY更容易编写如下:

SELECT Student_Master.*, InfoCount
FROM Student_Master
OUTER APPLY (SELECT COUNT(*) InfoCount FROM Student_Details
WHERE Student_Details.Student_Id=Student_Master.Student_Id ) InfoCounts
WHERE InfoCount>0

这也作为查询计划进行了优化,如下所示: enter image description here