“Having”子句如何在这个示例中创建正确的输出?

huangapple go评论82阅读模式
英文:

How is the having clause creating the correct output in this example?

问题

以下是要翻译的内容:

在SQLite中,HAVING子句的工作原理是什么?我的代码可以正常工作,并返回每个部门中薪水最高的人的姓名和部门。然而,我不明白为什么要使用HAVING子句,因为它应该只是筛选具有max(salary)为false值的分组:

CREATE TABLE salaries AS
  SELECT 'Alpha' as name, 'computer' as division, 500 as salary UNION
  SELECT 'Bravo', 'computer', 600 UNION
  SELECT 'Charlie', 'accounting', 200 UNION
  SELECT 'Delta', 'accounting', 300 UNION
  SELECT 'Echo', 'management', 800 UNION
  SELECT 'Foxtrot', 'management', 900;

SELECT name, division FROM salaries GROUP BY division HAVING max(salary);

为什么上述查询产生与此查询相同的输出:

SELECT name, division
FROM salaries AS s
WHERE salary = (
  SELECT MAX(salary)
  FROM salaries
  WHERE division = s.division
);
英文:

How the HAVING clause works in SQLite? My code works and returns the name and division of the highest paid person in each division. However, the use of the HAVING clause does not make sense to me since it should simply filter the groups with a false value for max(salary):

CREATE TABLE salaries AS
  SELECT 'Alpha' as name, 'computer' as division, 500 as salary UNION
  SELECT 'Bravo', 'computer', 600 UNION
  SELECT 'Charlie', 'accounting', 200 UNION
  SELECT 'Delta', 'accounting', 300 UNION
  SELECT 'Echo', 'management', 800 UNION
  SELECT 'Foxtrot', 'management', 900;

SELECT name, division FROM salaries GROUP BY division HAVING max(salary);

Why does the above query produce the same output as this query:

SELECT name, division
FROM salaries AS s
WHERE salary = (
  SELECT MAX(salary)
  FROM salaries
  WHERE division = s.division
);

答案1

得分: 0

然而,对于我来说,使用HAVING子句并没有太多意义,因为它应该只是过滤出最大薪水为false值的组。

只有当每个组的最大薪水为0时,才会这样:如果指定了HAVING子句,则将其视为每组行的布尔表达式进行评估。如果评估HAVING子句的结果为false,则会丢弃该组。如果HAVING子句是一个聚合表达式,则会跨组中的所有行进行评估。如果HAVING子句是非聚合表达式,则将其相对于组中任意选择的行进行评估。HAVING表达式可以引用不在结果中的值,甚至是聚合函数。https://www.sqlite.org/lang_select.html#generation_of_the_set_of_result_rows

所以,如果您例如使用以下查询:

CREATE TABLE salaries AS
SELECT 'Alpha' as name, 'computer' as division, 500 as salary UNION
SELECT 'Bravo', 'computer', 600 UNION
SELECT 'Charlie', 'accounting', 200 UNION
SELECT 'Delta', 'accounting', 300 UNION
SELECT 'Echo', 'management', 800 UNION
SELECT 'Foxtrot', 'management', 900 UNION
SELECT 'Hotel', 'other', 0; /*<<<<<<<<<<< ADDED for demo */

SELECT name, division, max(salary) AS msal FROM salaries GROUP BY division HAVING max(salary);

SELECT name, division, salary AS msal
FROM salaries AS s
WHERE salary = (
SELECT MAX(salary)
FROM salaries
WHERE division = s.division
);

即另一部门的薪水为0,则第一个查询的结果如下:

“Having”子句如何在这个示例中创建正确的输出?

即“other”部门的组已被删除,因为max(salary)为false(0)。

而第二个查询的结果包括“other”部门:

“Having”子句如何在这个示例中创建正确的输出?

英文:

> However, the use of the HAVING clause does not make much sense to me since it should simply filter out the groups with a false value for max(salary)

It would ONLY if the max(salary) per group was 0, according to:-

> If a HAVING clause is specified, it is evaluated once for each group of rows as a boolean expression. If the result of evaluating the HAVING clause is false, the group is discarded. If the HAVING clause is an aggregate expression, it is evaluated across all rows in the group. If a HAVING clause is a non-aggregate expression, it is evaluated with respect to an arbitrarily selected row from the group. The HAVING expression may refer to values, even aggregate functions, that are not in the result. https://www.sqlite.org/lang_select.html#generation_of_the_set_of_result_rows

So if you used, for example:-

CREATE TABLE salaries AS
  SELECT &#39;Alpha&#39; as name, &#39;computer&#39; as division, 500 as salary UNION
  SELECT &#39;Bravo&#39;, &#39;computer&#39;, 600 UNION
  SELECT &#39;Charlie&#39;, &#39;accounting&#39;, 200 UNION
  SELECT &#39;Delta&#39;, &#39;accounting&#39;, 300 UNION
  SELECT &#39;Echo&#39;, &#39;management&#39;, 800 UNION
  SELECT &#39;Foxtrot&#39;, &#39;management&#39;, 900 UNION
  SELECT &#39;Hotel&#39;, &#39;other&#39;, 0; /*&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; ADDED for demo */
  
SELECT name, division, max(salary) AS msal FROM salaries GROUP BY division HAVING max(salary);


SELECT name, division, salary AS msal
FROM salaries AS s
WHERE salary = (
  SELECT MAX(salary)
  FROM salaries
  WHERE division = s.division
);
  • i.e. another row with a 0 salary for another division then the result of the first query is:-

“Having”子句如何在这个示例中创建正确的输出?

i.e. the group for the other division has been dropped as the max(salary) is false (0).

While the result of the second query includes the other division:-

“Having”子句如何在这个示例中创建正确的输出?

huangapple
  • 本文由 发表于 2023年8月9日 08:46:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76863914-2.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定