【问题标题】:Why doesn't Oracle SQL allow us to use column aliases in GROUP BY clauses?为什么 Oracle SQL 不允许我们在 GROUP BY 子句中使用列别名?
【发布时间】:2011-02-10 12:13:47
【问题描述】:

这是我在编写 SQL 查询时通常会遇到的情况。我认为在 GROUP BY 表达式中编写整个列(例如长大小写表达式、具有长参数的求和函数)而不是别名会使查询更长且可读性更低。为什么 Oracle SQL 不允许我们在 GROUP BY 子句中使用列别名?这背后一定有一个重要的原因。

【问题讨论】:

  • 当然,在 Oracle 中,您可以使用子查询 - 例如SELECT g, SUM(n) FROM (SELECT my-complicated-expression AS g, n FROM bla) GROUP BY g :)
  • @JeffreyKemp。您应该将此作为答案发布。如果“不,你不能”的答案可以收集 21 票(在撰写本文时),那么“是的,你可以”的答案会更有价值!
  • 我的评论并没有严格回答这个问题,它实际上只是一种解决方法。

标签: sql oracle group-by alias


【解决方案1】:

它不仅仅是 Oracle SQL,事实上我相信它符合 ANSI SQL 标准(尽管我没有这方面的参考资料)。原因是 SELECT 子句在逻辑上处理 GROUP BY 子句之后,所以在 GROUP BY 完成时别名还不存在。

也许这个有点荒谬的例子有助于澄清 SQL 正在避免的问题和歧义:

SQL> select job as sal, sum(sal) as job
  2  from scott.emp
  3  group by job;

SAL              JOB
--------- ----------
ANALYST         6000
CLERK           4150
MANAGER         8275
PRESIDENT       5000
SALESMAN        5600

【讨论】:

  • 也谢谢你和 +1 的好例子。
【解决方案2】:

我知道这是一个旧线程,但似乎用户问题并没有真正解决;这些解释很好地解释了为什么 group by 子句不允许您使用别名,但没有给出替代方案。

根据上面的信息,别名不能在 group by 中使用,因为 group by 先运行,然后 select 子句中的别名存储在内存中。因此,对我的观点有效的简单解决方案是添加一个外部选择,它只选择别名,然后在同一级别进行分组。

例子:

SELECT alias1, alias2, alias3, aliasN
FROM
(SELECT field1 as alias1, field2 as alias2, field3 as alias3, fieldN as aliasN
 FROM tableName
 WHERE ' ' = ' ')
GROUP BY alias1, alias2, alias3, aliasN

一旦您看到解决方案就非常直接,但如果您是第一次尝试自己解决问题,那就是 PITA。

这是我能够从 case 语句中为派生字段“分组依据”的唯一方法,所以这是一个很好的技巧。

【讨论】:

  • 虽然这可能是一个“解决方案”,但它确实要求数据库无缘无故地做额外的工作。在这种情况下,输入额外的几个字符......这就是你被雇用的原因。
  • @Ben,它不一定会导致更多的工作。 Oracle 长期以来一直能够将子查询滚动到主查询中。很少需要在查询中重复自己。
【解决方案3】:

虽然我同意在 GROUP BY 子句中引用具有别名的表达式会有所帮助,但我的猜测是这是不可能的,因为 GROUP BY 子句是在 SELECT 子句之前评估的。

这也解释了为什么您可以在 ORDER BY 子句中使用列别名(即:最后评估 ORDER BY 子句)。

【讨论】:

  • 所以看起来正确的问题应该是“为什么我们不能在 group-by 子句中定义别​​名,并在 select 子句中重用它们?”。
  • @nadavwr 1) 并非所有查询都有 GROUP BY,2) 并非所有列都是 GROUPed BY。 SELECT 子句是定义别名最合乎逻辑的地方,这就是 SQL 标准中定义它的原因。此外,不能在 group by 中定义别名是一个小不便,如果您不想键入,可以轻松使用子查询:)
【解决方案4】:

虽然这似乎是一个合乎逻辑的答案,但实际上它是一个对用户非常不友好的答案。 在处理查询之前,Oracle 会读取它,并且通过读取它,预处理器可以用原始语句替换别名,并且仍然将正确的查询发送到数据库。 就像您可以按 1,2,3 编码顺序一样,您也应该可以按 1,2,3 或别名进行分组。

【讨论】:

    【解决方案5】:

    但有些 RDBMS 可以,这适用于 PostgreSQL:

    select emp.lastname || ' ' || emp.firstname as fullname, count(emp_work.*) as cnt
    from emp
    left join emp_work using(emp_id)
    group by fullname
    

    这样可以,只要分组别名不是聚合函数的结果,group by cnt 就不起作用

    但我可以大胆猜测group by fullname 会扩展为group by emp.lastname || ' ' || emp.firstname as fullname,而 SELECT 子句只是从该分组中选择全名结果;虽然在语法上它看起来相反。 GROUP 总是先执行,然后是投影最后(即 SELECT)

    【讨论】:

    • 好老的 FoxPro(我相信 dBase,虽然那是很久以前的事了)也支持别名 group by。后来我很惊讶地发现,如此基本的东西在 Oracle 这样的主要 DBMS 上不起作用。正如有人已经指出的那样,即使先评估 group by,为什么不让预处理器来处理呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    相关资源
    最近更新 更多