SQL-在分组方式中使用别名

SQL-在分组方式中使用别名,sql,group-by,alias,Sql,Group By,Alias,只是好奇SQL语法。所以如果我有 SELECT itemName as ItemName, substring(itemName, 1,1) as FirstLetter, Count(itemName) FROM table1 GROUP BY itemName, FirstLetter 这是不正确的,因为 GROUP BY itemName, FirstLetter 真的应该 GROUP BY itemName, substring(itemName, 1,1) 但是为什么我

只是好奇SQL语法。所以如果我有

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter
这是不正确的,因为

GROUP BY itemName, FirstLetter 
真的应该

GROUP BY itemName, substring(itemName, 1,1)

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

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

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

当然,如果您以交互方式执行此操作,并且编辑查询以更改结果中列的数量或顺序,那么这将是一个难题。但仍然如此

某些DBMS允许您使用别名,而不必重复整个表达式。
Teradata就是这样一个例子

我避免使用比尔推荐的顺序位置符号,原因记录在

简单而可靠的替代方法是始终重复GROUPBY子句中的表达式。

DRY不适用于SQL。

您可以始终使用子查询,以便使用别名;当然,请检查性能(db服务器可能会同时运行这两个服务器,但不会影响验证):


回到那天,我发现Rdb(Oracle现在支持的前DEC产品)允许在GROUP by中使用列别名。主流Oracle版本11不允许在GROUP BY中使用列别名。不确定Postgresql、SQL Server、MySQL等是否允许。YMMV。

由于处理的逻辑顺序,SQL Server不允许您引用GROUP BY子句中的别名。GROUP BY子句在SELECT子句之前处理,因此在计算GROUP BY子句时,别名是未知的。这也解释了为什么可以在ORDER BY子句中使用别名


以下是有关的信息来源。

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

  • FROM子句
  • WHERE子句
  • 分组依据子句
  • 有从句
  • SELECT子句
  • 按条款订货
  • 对于大多数关系数据库系统,此顺序解释了哪些名称(列或别名)是有效的,因为它们必须在上一步中引入

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


    不过也有例外:MySQL和Postgres似乎有额外的智能性,这使得它能够使用。

    在SQLite中对视图中的结果进行分组时,要小心使用别名。如果别名与任何基础表(视图)的列名相同,您将得到意外结果。

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

    -- Working example in postgres
    select col1 as col1_1, avg(col3) as col2_1
    from
        (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)
    from
        (select gender as col1, maritalstatus as col2,
        yearlyincome as col3 from customer) as layer_1
    group by col1;
    

    我没有回答为什么会这样,只是想通过使用
    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
    

    至少在Postgres中,您可以在group by子句中使用别名:

    挑选 itemName作为ItemName1, 子字符串(itemName,1,1)作为第一个字母, 计数(项目名称) 来自表1 按项目名称1分组,第一个字母


    我不建议将别名重命名为大写形式的更改,这会导致混淆。

    Postgresql中允许按首字母分组。也就是说,试着在Postgresql中运行它:从信息\u schema.tables分组中选择子字符串(表\u name,1,2)作为tnametname@MichaelBuen对我来说似乎有潜在的问题。通过快速测试,似乎有一个别名和一个具有相同名称的基表列,后者获得优先级。因此,如果通过别名依赖此组,以后的架构更改可能会悄悄地打断您的查询并更改语义。@MartinSmith现在才知道这是一个问题,将不再使用它,谢谢。考虑到PostgreSQL允许该快捷方式,他们应该给别名一个优先级,否则他们根本不应该允许该快捷方式。当你试图对任何包含聚合函数或窗口函数的表达式进行分组时,你会感到困惑,这“显然”不起作用。PostgresqlMySQL允许它也允许你谈论的是哪种rdbms?我喜欢这个解释。尽管我无法推测将其作为语法糖添加到引擎中有多困难,但您知道DB是否足够聪明,能够在不重新评估表达式的情况下实现SELECT和GROUP BY子句中的相同表达式吗?i、 e.如果存在
    按子字符串分组(itemName,1,1)
    ,数据库是否足够聪明,不会承受在SELECT子句中重新计算子字符串的性能损失?在带分组的查询的SELECT子句中,您只能访问GROUP BY表达式和聚合值。因此,这与聪明无关;必须以这种方式实现分组才能工作。(这是SQL标准所要求的)。但即使在更简单的情况下(例如WHERE和SELECT子句中的相同表达式),最先进的数据库系统也肯定只会计算一次。这种优化称为公共子表达式消除。执行顺序与问题有什么关系?这不像是询问者试图在COUNT()上分组。事实上,在MySQL和PostgreSQL中,按要求的查询工作得很好,正如评论中指出的那样。对于MySQL,
    sql\u模式
    不包括在位掩码中,优化器有机会在
    HAVING
    子句中对别名进行不同的使用。由于性能不佳,应尽可能避免子查询。使用函数的副本要好得多,因为它当然是由数据库优化程序检测到的,并且只执行一次。@Roland,但在这种情况下,执行计划没有什么不同。还有其他性能考虑吗?@Roland,相关子查询o
    SELECT 
     itemName as ItemName,
     FirstLetter,
     Count(itemName)
    FROM table1
    CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
    GROUP BY itemName, FirstLetter