为什么 Oracle SQL 不允许我们在 GROUP BY 子句中使用列别名?

发布于 2024-08-29 07:37:06 字数 149 浏览 3 评论 0原文

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

This is a situation I'm generally facing while writing SQL queries. I think that writing the whole column (e.g. long case expressions, sum functions with long parameters) instead of aliases in GROUP BY expressions makes the query longer and less readable. Why doesn't Oracle SQL allow us to use the column aliases in GROUP BY clause? There must be an important reason behind it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

还如梦归 2024-09-05 07:37:06

它不仅仅是 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

It isn't just Oracle SQL, in fact I believe it is conforming to the ANSI SQL standard (though I don't have a reference for that). The reason is that the SELECT clause is logically processed after the GROUP BY clause, so at the time the GROUP BY is done the aliases don't yet exist.

Perhaps this somewhat ridiculous example helps clarify the issue and the ambiguity that SQL is avoiding:

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
单挑你×的.吻 2024-09-05 07:37:06

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

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

示例:

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 语句中的派生字段进行“分组”的唯一方法,因此这是一个值得了解的好技巧。

I know this is an old thread, but it seems the users problem wasn't really solved; the explanations were good in explaining why the group by clause doesn't let you use aliases, but no alternative was given.

Based on the info above, the aliases can't be used in the group by since group by runs first, before aliases from the select clause are stored in memory. So the simple solution which worked for my view was to add an outer select which simply selects the aliases, and then groups at that same level.

Example:

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

Pretty straight forward once you see the solution, but a PITA if trying to figure out by yourself for first time.

This is the only way I have been able to "group by" for a derived field from a case statement, so this is a good trick to know.

以往的大感动 2024-09-05 07:37:06

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

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

While I agree it would be helpful to reference expressions with aliases in the GROUP BY clause, my guess is that it is not possible because the GROUP BY clause is evaluated before the SELECT clause.

This would also explain why you can use column aliases in the ORDER BY clause (i-e: the ORDER BY clause is evaluated last).

七色彩虹 2024-09-05 07:37:06

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

While it seems a logical answer, in fact it's a very user-unfriendly one.
Prior to processing the query Oracle reads it, and by reading it the preprocessor can replace the alias by the original statement and still send the correct query to the database.
same as you can code order by 1,2,3, you should also be able to group by 1,2,3 or alias.

烟酉 2024-09-05 07:37:06

但有些 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)

But some RDBMS do, this works on 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

That will work, as long as the grouped alias is not the result of aggregate functions, group by cnt will not work

But I can hazard a guess that group by fullname gets expanded to group by emp.lastname || ' ' || emp.firstname as fullname, and the SELECT clause just pick the fullname result from that grouping; though syntactically it looks the other way around. GROUP always executes first, then projections last(i.e. SELECT)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文