我可以在 HAVING 子句中的关系的单个列名上写条件吗

Can I write a condition on a single column name of a relation in HAVING clause

考虑以下关系模式

customers(id, name, age, address, salary)

我尝试了一个查询

SELECT SUM(salary), age FROM customers             
GROUP BY age HAVING age > 23 ;                    ...(1)

我惊讶地发现它运行良好,而且我也可以在 HAVING 子句中编写单列条件。

即使这样也有效

SELECT SUM(salary), age FROM customers
GROUP BY age, salary HAVING age > 23 AND salary >2000;   ...(2)

否则,我应该这样写:(使用 WHERE 子句)

SELECT SUM(salary), age FROM customers
WHERE age > 23 GROUP BY age;                       ...(3)

SELECT SUM(salary), age FROM customers
WHERE age > 23 AND salary >2000 GROUP BY age, salary ;    ..(4)

但是当我尝试更多组合时,我发现

that column name must be present in GROUP BY clause also on which condition is applied in HAVING clause.

我是否正确,或者是否可以用任何其他方式在 HAVING 子句中编写单列条件?

为什么它有效,因为我之前研究过我们只能在 HAVING 子句中编写聚合函数的条件。

您大体上是正确的。重要的是理解分组。

使用 GROUP BY 时,服务器会扫描 'rows' 并将它们存储到一些 'groups' 中。然后每个 'group' 作为一个新行。当操作这些 'new lines' - 在 SELECT、HAVING 或 ORDER 子句中时 - 服务器需要知道其中的 'attribute values'。这些属性值是行属性值的聚合或具有这些聚合的表达式。

当在GROUP BY子句中使用某些属性或表达式时,它的聚合值是非常确定的,所以服务器给了我们简化过程的能力。我们可以这样写

SELECT object_type, count(*)
FROM user_objects
GROUP BY object_type
HAVING MAX(object_type) like '%O%'
ORDER BY MIN(object_type)

如果我们这样做就可以了。但是我们可以简单地写

SELECT object_type, count(*)
FROM user_objects
GROUP BY object_type
HAVING object_type like '%O%'
ORDER BY object_type

意思完全一样。如果列没有提到 GROUP BY 值 - 上面的规则不成立,所以我们不能直接使用它,没有聚合。

SELECT SUM(salary), age 
FROM customers
GROUP BY age, salary 
HAVING age > 23 AND salary >2000;

当您按这些分组时,这会为您提供每个年龄和薪水的记录。稍后您将删除一些结果行。工资的总和当然是工资本身。

例如,如果这些是您的记录:

salary  age  something
1000    30    100
1000    30    200    
2000    30    300    
2000    40    400

然后你这样分组:

salary  age  something
1000    30    100
              200    
2000    30    300    
2000    40    400

对于 1000/30 组,sum(something) 为 300,avg(something) 为 150。但是 sum(salary) 为 1000,avg(salary) 为 1000,min(salary) 为 1000,并且依此类推,因为这只是您所说的一个工资值。

HAVING 子句然后从结果中删除年龄超过 23 岁且薪水超过 2000 的行。您可以使用 WHERE 子句从评估中删除这些记录,从而节省 dbms 的一些工作。但是你让 dbms 首先收集所有年龄和薪水组,然后才说出你解雇了哪些。

我同意,如果 DBMS 提出一个错误,告诉您 sum(salary) 没有意义,因为它只是该组的一个薪水,那会更好。