添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

但为什么我们不能为了方便而简单地使用前者呢?

4 个评论
这在Postgresql中是允许的
Kip
MySQL也允许它
你说的是哪种rdbms?
这个问题并不专指 group by ,也包括 join ,例如
sql
group-by
alias
Haoest
Haoest
发布于 2010-10-02
10 个回答
Codo
Codo
发布于 2020-09-24
已采纳
0 人赞同

SQL的实现就像一个查询按以下顺序执行一样。

  • FROM子句
  • WHERE子句
  • GROUP BY子句
  • HAVING子句
  • SELECT子句
  • ORDER BY子句
  • 对于大多数关系型数据库系统来说,这个顺序解释了哪些名称(列或别名)是有效的,因为它们必须是在前一个步骤中引入的。

    所以在Oracle和SQL Server中,你不能在GROUP BY子句中使用你在SELECT子句中定义的术语,因为GROUP BY会在SELECT子句之前执行。

    不过也有例外。MySQL和Postgres似乎有额外的智能,允许它。

    我喜欢这种解释。尽管我无法推测把它作为语法糖添加到引擎中是多么困难。
    Kip
    知道数据库是否足够聪明,能够意识到同一表达式在SELECT和GROUP BY子句中,而不重新评估表达式?也就是说,如果有 GROUP BY substring(itemName, 1,1) ,数据库是否足够聪明,不会因为重新计算SELECT子句中的子串而影响性能?
    Codo
    在有分组的查询的SELECT子句中,你只能访问GROUP BY表达式和聚集的值。所以,这不是聪明的问题;为了分组工作,它必须这样实现。(而且这是SQL标准的要求)。但是,即使在更微不足道的情况下(例如,在WHERE和SELECT子句中的相同表达式),最先进的数据库系统也肯定只会计算一次。这种优化被称为 普通子表达式 的消除。
    执行顺序与这个问题有什么关系? 问者又不是要在COUNT()上进行GROUP BY。 事实上,正如评论中指出的那样,所问的查询在MySQL和PostgreSQL中都能正常工作。
    Drew
    对于mysql, sql_mode ,不包括位掩码中的 ONLY_FULL_GROUP_BY ,优化器有机会在 HAVING 子句中对别名进行不同/ 不同的 使用,从而提供 更好的结果
    Chris Shaffer
    Chris Shaffer
    发布于 2020-09-24
    0 人赞同

    你总是可以使用一个子查询,这样你就可以使用别名;当然,检查一下性能(可能数据库服务器将运行两者一样,但验证一下总不会有坏处)。

    SELECT ItemName, FirstLetter, COUNT(ItemName)
    FROM (
        SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
        FROM table1
        ) ItemNames
    GROUP BY ItemName, FirstLetter
        
    由于性能不佳,应该尽可能避免子查询。使用函数的副本要好得多,因为它当然会被数据库优化器检测到,而且只做一次。
    @Roland,但在这种情况下,执行计划并无不同。有什么其他的性能考虑吗?
    @Roland, 应该避免相关的子查询或其他导致循环或逐行行为的语法,而且你应该对嵌套子查询的深度进行限制,但一般来说,子查询会导致糟糕的性能,这并 不是真的 。在这种情况下,正如Chris所说,你可以验证执行计划(又称查询计划,解释计划),比较有子查询和没有子查询的情况,看看是否真的有什么不同。几乎每一个数据库引擎都会重写你的查询,所以你并不能完全控制执行的内容。这就是声明性语法的意义所在。
    Bill Gribble
    Bill Gribble
    发布于 2020-09-24
    0 人赞同

    至少在PostgreSQL中,你可以在GROUP BY子句中使用结果集中的列号。

    SELECT 
     itemName as ItemName,
     substring(itemName, 1,1) as FirstLetter,
     Count(itemName)
    FROM table1
    GROUP BY 1, 2
    

    当然,如果你是以交互方式进行,并且你编辑查询以改变结果中列的数量或顺序,这就开始变得很麻烦了。但是,仍然如此。

    GROUP BY FirstLetter 在Postgresql中是允许的。 在Postgresql中试着运行这个:select substring(table_name,1,2) as tname from information_schema.tables group by tname
    @MichaelBuen 对我来说似乎有潜在的问题。从一个快速测试来看,如果有一个别名和一个基表的列有相同的名字,那么后者就会得到优先权? SQL Fiddle 。因此,如果依靠这个别名组,后来的模式变化可能会悄悄地破坏你的查询,改变语义。
    @MartinSmith 现在才知道这是个陷阱,将避免使用这个,谢谢。鉴于PostgreSQL允许这个快捷方式,他们应该给别名一个优先权,否则他们根本就不应该允许这个快捷方式。
    这是PostgreSQL设计者的一个糟糕的想法。只要你试图将任何包含聚合函数或窗口函数的表达式 GROUP BY ,就会产生混乱,这 "显然 "是不行的。
    bobs
    bobs
    发布于 2020-09-24
    0 人赞同

    由于逻辑上的处理顺序,SQL Server不允许你在GROUP BY子句中引用别名。 GROUP BY子句是在SELECT子句之前处理的,所以当GROUP BY子句被评估的时候,别名是不知道的。 这也解释了为什么你可以在ORDER BY子句中使用别名。

    这里有一个关于 SQL Server逻辑处理阶段 的信息来源。

    Ricardo
    Ricardo
    发布于 2020-09-24
    0 人赞同

    我并没有回答为什么会这样,只是想通过使用 CROSS APPLY 来创建别名,来展示一个在SQL Server中绕过这个限制的方法。然后你在 GROUP BY 子句中使用它,像这样。

    SELECT 
     itemName as ItemName,
     FirstLetter,
     Count(itemName)
    FROM table1
    CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
    GROUP BY itemName, FirstLetter
        
    Shannon S
    Shannon S
    发布于 2020-09-24
    0 人赞同

    注意,在Group By中使用别名(对于支持它的服务,如postgres)可能会产生意想不到的结果。例如,如果你创建的别名在内部语句中已经存在,Group By将选择内部字段的名称。

    -- Working example in postgres
    select col1 as col1_1, avg(col3) as col2_1
        (select gender as col1, maritalstatus as col2, 
        yearlyincome as col3 from customer) as layer_1
    group by col1_1;
    -- Failing example in postgres
    select col2 as col1, avg(col3)
        (select gender as col1, maritalstatus as col2,
        yearlyincome as col3 from customer) as layer_1
    group by col1;
        
    mechanical_meat
    mechanical_meat
    发布于 2020-09-24
    0 人赞同

    一些DBMS会让你使用一个别名,而不是重复整个表达。
    Teradata就是这样一个例子。

    我避免使用Bill推荐的序数位置符号,原因在 这个SO问题 中已经记录。

    简单而有力的方法是在GROUP BY子句中重复表达。
    DRY并不适用于SQL。

    GGGforce
    GGGforce
    发布于 2020-09-24
    0 人赞同

    在SQLite中对视图的结果进行分组时要注意使用别名。 如果别名的名称与任何底层表的列名相同,你会得到意想不到的结果(对视图而言)。

    0 人赞同

    在过去,我发现Rdb,以前的DEC产品现在被Oracle支持,允许在GROUP BY中使用列的别名。 主流的Oracle到11版都不允许在GROUP BY中使用列别名。 不确定Postgresql、SQL Server、MySQL等是否允许。 请自行斟酌。

    rogerdpack
    rogerdpack
    发布于 2020-09-24
    0 人赞同

    至少在Postgres中,你可以在group by子句中使用别名名称。

    SELECT itemName作为ItemName1。