我很惊讶地发现以下作品:
SELECT name, height * weight as inchpounds
FROM sashelp.class
HAVING inchpounds > 5000;
因为我认为HAVING子句是在SELECT子句之前严格处理的。这对我来说实际上是一个错误的假设吗?或者这是SAS的SQL实现特有的吗?
答案 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
意味着所有行都有聚合,因此只有聚合函数会允许HAVING
和SELECT
条款。
查看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实施而言,WHERE
和HAVING
子句之间的唯一区别是“何时”应用它们。 WHERE
子句适用于创建中间结果(构建包含SELECT
语句中列出的列的临时表)和HAVING
子句控制将哪些行写入最终表。< / p>
或者,可以在CALCULATED
声明中使用WHERE
关键字:
SELECT name, height * weight as inchpounds
FROM sashelp.class
WHERE CALCULATED inchpounds > 5000;
答案 3 :(得分:0)
这对我来说实际上是错误的假设吗?
可能是假的。查询计划程序将根据数据库和数据库具有的统计信息来决定如何运行查询。
考虑以特定顺序运行的不同子句有助于编写和推理查询,但这并不是大多数SQL数据库实际工作的方式。