webdevqa.jp.net

Oracle SQLでは、GROUP BY句で列のエイリアスを使用できないのはなぜですか?

これは、SQLクエリの作成中に私が一般的に直面している状況です。 GROUP BY式でエイリアスの代わりに列全体(長いケース式、長いパラメーターを持つ合計関数など)を書き込むと、クエリが長くなり、読みにくくなると思います。 Oracle SQLでは、GROUP BY句で列のエイリアスを使用できないのはなぜですか?その背後には重要な理由があるはずです。

26

これはOracle SQLだけではなく、実際にはANSI SQL標準に準拠していると私は信じています(ただし、そのリファレンスはありません)。その理由は、SELECT句が論理的に処理されるafter 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
45
Tony Andrews

これは古いスレッドですが、ユーザーの問題は実際には解決されなかったようです。説明は、group by句でエイリアスを使用できない理由を説明するのに役立ちましたが、代替案がありませんでした。

上記の情報に基づいて、select by句のエイリアスがメモリに格納される前にgroup byが最初に実行されるため、エイリアスは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ステートメントからの派生フィールドを「グループ化」できる唯一の方法なので、知っておくと便利です。

13
keith

それは論理的な答えのようですが、実際には非常にユーザーフレンドリーではありません。クエリを処理する前に、Oracleはそれを読み取り、それを読み取ることにより、プリプロセッサはエイリアスを元のステートメントで置き換えても、正しいクエリをデータベースに送信できます。 1,2,3でコード順をコーディングできるのと同じように、1,2,3またはエイリアスでグループ化することもできます。

3
Tom Heitbrink

GROUP BY句でエイリアスを使用して式を参照すると役立つことに同意しますが、GROUP BY句が評価されるため、不可能ですbefore SELECT句。

これは、ORDER BY句で列エイリアスを使用できる理由も説明します(つまり、ORDER BY句が最後に評価されます)。

3
Vincent Malgrat

しかし、一部の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 fullnamegroup by emp.lastname || ' ' || emp.firstname as fullnameに展開され、SELECT句がそのグループからのフルネームの結果を選択するだけだと推測して危険を冒すことができます。構文的には逆ですが。 GROUPは常に最初に実行され、次にプロジェクションが最後に実行されます(つまり、SELECT)

2
Michael Buen