为什么我不能在having子句中为聚合使用别名?

时间:2012-12-27 02:26:59

标签: sql sql-server-2008

我的代码如下所示:

select col1,count(col2) as col7
from --some join operation
group by col1
having col7 >= 3 -- replace col7 by count(col2) to make the code work

我的代码导致错误“无效的列名'col7'”。为什么会这样? SQL不允许我在最后一行使用col7似乎不合逻辑。

我正在使用SQL server express 2008

8 个答案:

答案 0 :(得分:23)

HAVING之前评估SELECT子句 - 因此服务器还不知道该别名。

  1. 首先,形成FROM子句中所有表的乘积。

  2. 然后评估WHERE子句以消除不满足search_condition的行。

  3. 接下来,使用GROUP BY子句中的列对行进行分组。

  4. 然后,消除了不满足search_condition子句中HAVING的组。

  5. 接下来,评估SELECT语句目标列表中的表达式。

  6. 如果select子句中存在DISTINCT关键字,则现在会删除重复的行。

  7. 评估每个子选择后都会UNION

  8. 最后,根据ORDER BY子句中指定的列对生成的行进行排序。

  9. TOP子句已执行。

  10. 希望这能回答你的问题。此外,它解释了为什么别名在ORDER BY子句中起作用。

答案 1 :(得分:22)

在MS SQL中,唯一可以引用别名的地方(我知道)在ORDER BY子句中。在查询的其他部分引用别名的能力是许多其他数据库平台所具有的功能,老实说,它让我很恼火,微软并没有认为它是一个足够有用的功能来添加它。

答案 2 :(得分:3)

尝试使用此选项,因为选择列表包含您可以在having子句中使用的相同表达式:

SELECT COL1,COUNT(COL2) AS COL7
FROM --SOME JOIN OPERATION
GROUP BY COL1
HAVING COUNT(COL2) >= 3 

答案 3 :(得分:2)

您应该选择两次以使用count()列

select * from (select col1,count(col2) as col7
from --some join operation
group by col1) as temp
where temp.col7 >= 3

答案 4 :(得分:1)

你可以使用这段代码:

IF OBJECT_ID('tempdb..#temp') is not null DROP TABLE #temp

-- Create tempurary table
CREATE TABLE #temp (Id BIGINT IDENTITY(1,1), col1 BIGINT, countOfcol2 BIGIN)

--insert from the table 2 #temp
INSERT INTO #temp (col1,countOfcol2) 

select col1,count(col2) as col7
from --some join operation

select col1,countOfcol2 from #temp
group by col1
having countOfcol2 >= 3 -- replace col7 by count(col2) to make the code work

答案 5 :(得分:1)

您可以使用嵌套查询解决此问题。

当我想提高性能时,我也遇到了这个问题。我需要根据表中JSON字段中的某些字段运行count(),显然我们只需要解析一次JSON,而不必在where或{{{{}}中包含单独的计数1}}子句(特别是像我这样的昂贵的子句)。

如果have是唯一ID,那么计算效率最高的方法可能是将计数嵌套在单独的col1

select

这样计数只运行一次,创建一种临时查找表供查询的其余部分参考。

同样,这只适用于select col1, innerquery.col7 from whatevertable inner join (select col1, count(col2) as col7 from whatevertable group by col1) as innerquery on innerquery.col1 = whatevertable.col1 where innerquery.col7 >= 3; 对于每条记录都是唯一的,由于大多数表都有某种id主键,因此通常不会太多问题。

答案 6 :(得分:0)

选择col1,count(col2)为col7 来自--some join操作 按col1分组 计数(col2)> = 3;

老实说,我对SQL Server为什么不处理列别名感到恼火。我用这个作为解决方法。它仍然将列名称打印为您的别名,但使用原始聚合函数进行处理。

答案 7 :(得分:0)

在SQL中,子句的执行流程为: 从->其中->分组依据->具有->选择->排序依据->不重复->顶部。

因为别名在select子句中声明,所以它不适用于在select之前执行的子句(仅在select之后执行的子句才可用) 但是还有另一种使用别名的方法,即使用嵌套选择 例如:从*中选择*,(从雇员中选择姓名,薪水,薪金+1000作为加薪)作为emp,其中加薪> 10000;