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

How can I use output of sub-query in SELECT clause in WHERE clause?

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

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

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

预期输出:-

Student_Id  Student_Name    InfoCount
1           A               1
2           B               3

以下是不正确的语法,但为了解释我正在尝试做的事情:-

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

但是在这里,我必须写两次相同的子查询。这个子查询将执行两次并且会影响性​​能。大师table有2500万条记录,详情table有1亿条记录。

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

如果您只是 Inner Join 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 的记录,那么您可以使用 Group By Having

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

使用 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

这里也优化为查询计划如下: