在SQL中,是在SELECT之前还是之后进行了HAVING处理?

时间:2013-01-02 14:06:25

标签: sql sas

我很惊讶地发现以下作品:

    SELECT name, height * weight as inchpounds
    FROM sashelp.class 
    HAVING inchpounds > 5000;

因为我认为HAVING子句是在SELECT子句之前严格处理的。这对我来说实际上是一个错误的假设吗?或者这是SAS的SQL实现特有的吗?

4 个答案:

答案 0 :(得分:3)

严格来说,如果我记得很清楚,SQL标准会在HAVING子句之前定义SELECT子句。因此,SELECT中定义的别名不能在HAVING子句中使用。

在相关问题中查看我的回答: Using 'case expression column' in where clause 了解处理SELECT声明的顺序,即:

FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY 

因此,在大多数SQL版本中,该查询将产生错误。 MySQL是我所知道的一个例外,允许这种偏离标准(以及允许在SELECT子句中使用GROUP BY别名的地方。

正如注释中提到的@a_horse_with_no_name一样,查询在大多数SQL产品中也会因其他原因而失败:HAVING没有GROUP BY意味着所有行都有聚合,因此只有聚合函数会允许HAVINGSELECT条款。


查看SAS SQL documentation and examples后,上面发布的查询似乎在SAS SQL中有效,并以此身份执行(在标准SQL中):

SELECT name, height * weight AS inchpounds
FROM sashelp.class 
WHERE height * weight > 5000;

如果我理解正确,您也可以将聚合函数与非聚合列混合使用,如下所示:

SELECT name, height, 
       MAX(height) AS max_height
FROM sashelp.class ;

将被评估为(在标准SQL中):

SELECT name, height, 
       MAX(height) OVER () AS max_height
FROM sashelp.class ;

答案 1 :(得分:1)

SQL Standard指定解释子句的顺序,而不是它们的执行顺序。实际上,这意味着在having之后解析select子句,因此他们可以使用select语句中定义的变量。 SAS SQL与其他方言不同。您可以在select子句中使用where个变量。

SQL引擎可以自由地实际运行查询,但是他们喜欢。但是,您的问题不是运行查询,而是解析它。

使用没有having的{​​{1}}子句通常是可疑的。但是,我相信它应该适用于任何方言。唯一的问题是返回0行还是1个汇总行。

您的特殊查询工作令人惊讶。在大多数SQL方言中,您会收到错误,因为group by子句意味着聚合,而having中的值不在聚合函数中。这个唯一可行的方言是MySQL,因为它有一个叫做隐藏列的(错误)功能。 SAS SQL比标准SQL比其他方言更远。

答案 2 :(得分:1)

我无法就SQL“标准”发言,但就SAS实施而言,WHEREHAVING子句之间的唯一区别是“何时”应用它们。 WHERE子句适用于创建中间结果(构建包含SELECT语句中列出的列的临时表)和HAVING子句控制将哪些行写入最终表。< / p>

或者,可以在CALCULATED声明中使用WHERE关键字:

SELECT name, height * weight as inchpounds
FROM sashelp.class 
WHERE CALCULATED inchpounds > 5000; 

答案 3 :(得分:0)

  

这对我来说实际上是错误的假设吗?

可能是假的。查询计划程序将根据数据库和数据库具有的统计信息来决定如何运行查询。

考虑以特定顺序运行的不同子句有助于编写和推理查询,但这并不是大多数SQL数据库实际工作的方式。