我有以下两张表:

1. Lecturers (LectID, Fname, Lname, degree).
2. Lecturers_Specialization (LectID, Expertise).

我想找到最专业的讲师。 当我尝试这个,它是不工作:

SELECT
  L.LectID, 
  Fname, 
  Lname 
FROM Lecturers L, 
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
AND COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);

但当我尝试这个时,它起作用了:

SELECT
  L.LectID,
  Fname,
  Lname 
FROM Lecturers L,
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
GROUP BY L.LectID,
         Fname,
         Lname 
HAVING COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID); 

原因是什么?谢谢。


当前回答

HAVING操作在聚合上。因为COUNT是一个聚合函数,所以不能在WHERE子句中使用它。

这里有一些来自MSDN关于聚合函数的阅读。

其他回答

首先,我们应该了解条款的执行顺序 从>,>组>有>不同>选择>顺序。 由于WHERE子句在GROUP BY子句之前执行,因此不能通过将WHERE应用于GROUP BY应用的记录来过滤记录。

HAVING与WHERE子句相同,但应用于分组记录。

首先,WHERE子句根据条件获取记录,然后GROUP BY子句相应地对它们进行分组,然后HAVING子句根据HAVING条件获取组记录。

在一个查询中没有看到两者兼有的例子。这个例子可能会有帮助。

  /**
INTERNATIONAL_ORDERS - table of orders by company by location by day
companyId, country, city, total, date
**/

SELECT country, city, sum(total) totalCityOrders 
FROM INTERNATIONAL_ORDERS with (nolock)
WHERE companyId = 884501253109
GROUP BY country, city
HAVING country = 'MX'
ORDER BY sum(total) DESC

它首先根据companyId对表进行过滤,然后对表进行分组(按国家和城市),并将其过滤到墨西哥的城市集合。在聚合中不需要companyId,但我们能够在使用GROUP BY之前使用WHERE过滤出我们想要的行。

1. 我们可以使用带有HAVING子句而不是WHERE子句的聚合函数,例如min,max,avg。

2. WHERE子句逐个删除记录元组 HAVING子句将整个组从group集合中删除

大多数情况下,HAVING在数据组中使用,WHERE在数据行中使用。

WHERE子句可以用于SELECT、INSERT和UPDATE语句,而HAVING只能用于SELECT语句。 WHERE在聚合之前过滤行(GROUP BY),而HAVING在执行聚合之后过滤组。 聚合函数不能在WHERE子句中使用,除非它包含在HAVING子句中,而聚合函数可以在HAVING子句中使用。

WHERE子句用于消除关系中的元组,HAVING子句用于消除关系中的组。

HAVING子句用于聚合函数,例如 MIN,MAX,COUNT,SUM,但是总是在HAVING子句之前使用GROUP BY子句来最小化错误。