【问题标题】:Why can't I use alias in a count(*) "column" and reference it in a having clause?为什么我不能在计数(*)“列”中使用别名并在有子句中引用它?
【发布时间】:2010-01-15 00:45:00
【问题描述】:

我想知道为什么我不能在 count(*) 中使用别名并在 having 子句中引用它。例如:

select Store_id as StoreId, count(*) as _count
    from StoreProduct
    group by Store_id
        having _count > 0

行不通。但如果我删除 _count 并改用 count(*),它会起作用。

【问题讨论】:

    标签: sql sql-server alias


    【解决方案1】:

    answeryour recent question 中查看CodeByMoonlightdocument referenced

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

    1. 首先形成 from 子句中所有表的乘积。
    2. 然后评估 where 子句以消除不满足的行 search_condition。
    3. 接下来,使用 group by 子句中的列对行进行分组。
    4. 然后,不满足 中的 search_condition 的组 子句被删除。
    5. 接下来,select子句目标列表中的表达式为 评估。
    6. 如果 distinct 关键字出现在 select 子句中,则重复行 现已被淘汰。
    7. 联合是在评估每个子选择后进行的。
    8. 最后,根据列对结果行进行排序 在 order by 子句中指定。

    【讨论】:

    • 我要补充一点,评估顺序是 SQL 中的一个逻辑概念。实际上,查询优化器可以选择不同的操作顺序,只要结果与逻辑顺序相同即可。
    • 基本上select子句中定义的别名有两种用途:1)命名列2)排序
    • blog.sqlauthority.com/2009/04/06/… 并不是真正的问题,但他有一个很好的 sql 执行顺序列表。当然,某处还有更官方的列表。 1. 从 2. ON 3. 外部 4. WHERE 5. GROUP BY 6. CUBE | ROLLUP 7. HAVING 8. SELECT 9. DISTINCT 10 ORDER BY 11. TOP
    • 我有类似的例子,它适用于 MySQL、SqLite,但不适用于 MSSQL。是什么原因?
    • @cjava:“这是否意味着聚合函数将被计算两次”。对于 PostgreSQL,答案是否(在大多数情况下)符合以下问题:How to avoid invoking functions twice when using GROUP BY and HAVING?
    【解决方案2】:

    select 子句是逻辑上执行的最后一个子句,order by 除外。 having 子句出现在 select 之前,因此别名尚不可用。

    如果你真的想使用别名,我不建议这样做,可以使用内联视图来使别名可用:

    select StoreId, _count
    from (select Store_id as StoreId, count(*) as _count
        from StoreProduct
        group by Store_id) T
    where _count > 0
    

    或者在 SQL Server 2005 及更高版本中,CTE:

    ; with T as (select Store_id as StoreId, count(*) as _count
        from StoreProduct
        group by Store_id)
    select StoreId, _count
    from T
    where _count > 0
    

    【讨论】:

      【解决方案3】:

      您可以在 select 子句中使用 count 的别名,但不能在 having 语句中使用它,所以这可以工作

      select Store_id as StoreId, count(*) as _count
          from StoreProduct
          group by Store_id
              having count(*) > 0
      

      【讨论】:

        【解决方案4】:

        字段名称的别名仅用于命名结果中的列,它们永远不能在查询中使用。你也不能这样做:

        select Store_id as Asdf
        from StoreProduct
        where Asdf = 42
        

        但是,您可以安全地在两个地方使用count(*),数据库会识别出它是相同的值,因此不会计算两次。

        【讨论】:

          【解决方案5】:

          这是我的贡献(基于此处发布的代码):

          select * from (
            SELECT Store_id as StoreId, Count(*) as StoreCount 
            FROM StoreProduct
            group by Store_id
            ) data
          where data.StoreCount > 0
          

          【讨论】:

            【解决方案6】:

            您可以在 SQL 中为聚合使用别名,但这只是为了在结果标题中显示别名。但是,当您想要在其中使用聚合函数的条件时,您仍然需要使用聚合,因为它评估的是函数而不是名称。

            【讨论】:

              【解决方案7】:

              在 Hive 0.11.0 及更高版本中,如果 hive.groupby.orderby.position.alias 设置为 true,则可以按位置指定列。

              set hive.groupby.orderby.position.alias=true;
              select Store_id as StoreId, count(*) as _count
              from StoreProduct
              group by 1
              

              我不明白您查询的目的。 鉴于您发布的查询的上下文,您的条件不是必需的,因为不存在的项目,即。 e. count 0,永远不会是查询的结果...

              【讨论】:

                【解决方案8】:

                可能是因为这是 sql 定义命名空间的方式。举个例子:

                  select a as b, b as a
                    from table
                   where b = '5'
                order by a
                

                a 和 b 指的是什么?设计者只是选择让别名只出现在查询的“外部”。

                【讨论】:

                • 别名在order by 子句中可用。在您的示例中,结果将按别名为atable.b 排序。试试select 1 as a order by a。那将是有效的。这是由于求值的逻辑顺序,order by 在 select 之后,可以看到别名。
                猜你喜欢
                • 1970-01-01
                • 2012-06-15
                • 1970-01-01
                • 2011-02-10
                • 2012-01-12
                • 2021-06-17
                • 1970-01-01
                相关资源
                最近更新 更多