バインド引数が1つだけになるようにステートメントを書き直すことをお勧めします。このアプローチはちょっと醜いですが、結果セットを返します:
select max(col1)
, f_col2
from (
select col1
, f(? ,col2) as f_col2
from t
)
group
by f_col2
この書き直されたステートメントには単一のバインド引数のみへの参照があるため、DBMSはGROUPBY句の式を認識します。SELECTリストは同一です。
HTH
[編集]
(よりきれいな方法があればいいのですが、これがOracleが使用する名前付きバインド引数アプローチを好む理由です。PerlDBIドライバーを使用すると、位置引数は実際にOracleに送信されるステートメントで名前付き引数に変換されます。)
最初は問題がわかりませんでした。元の質問がわかりませんでした。 (どうやら、他の何人かの人々もそれを見逃していました。)しかし、いくつかのテストケースを実行した後、問題が何であるか、質問が何であるかがわかりました。
問題を述べることができるかどうかを見てみましょう:同じ(名前付き)バインド引数への2つの参照であるかのように(DBMSによって)扱われる2つの別々の(位置)バインド引数を取得する方法。
DBMSは、GROUPBYの式がSELECTリストの式と一致することを期待しています。ただし、2つの式は、式が同一である場合でも異なると見なされます。唯一の違いは、各式が異なるバインド変数を参照していることです。 (少なくとも一部のDBMSで許可されるいくつかのテストケースを示すことができますが、例外を発生させるより一般的なケースがあります。)
この時点での簡単な答えは、それは私を困惑させたということです。私が持っている提案(元の質問に対する実際の答えではないかもしれません)は、クエリを再構築することです。
[/編集]
このアプローチが機能しない場合、またはそれを理解するのに他の問題がある場合は、詳細を提供できます。または、パフォーマンスに問題がある場合(オプティマイザーが、指定された結果セットを返しても、書き換えられたクエリに対して別のプランを選択していることがわかります。さらにテストするには、どのDBMS、どのドライバー、統計など)
編集 (8年半後)
クエリの書き換えの別の試み。繰り返しますが、私が思いついた唯一の解決策は、1つのバインドプレースホルダーを使用したクエリです。今回は、単一の行を返すインラインビューに貼り付け、それをtに結合します。私はそれが何をしているのかを見ることができます。 Oracleオプティマイザがこれをどのように認識するかはわかりません。明示的な変換を実行したい(または必要な)場合があります。 TO_NUMBER(?) AS param
、TO_DATE(?,'...') AS param
、TO_CHAR(?) AS param
、バインドパラメータのデータ型、およびビューから返されるデータ型によって異なります。)
これは私がMySQLでそれを行う方法です。私の回答の元のクエリは、インラインビュー(MySQL派生テーブル)内で結合操作を実行します )。そして、それを避けることができれば、hughjass派生テーブルの具体化を避けたいと思います。繰り返しになりますが、MySQLはおそらく、sql_mode
である限り、元のクエリをスライドさせます。 ONLY_FULL_GROUP_BY
は含まれません 。 MySQLでは、FROM DUAL
も削除できます。 )
SELECT MAX(t.col1)
, f( v.param ,t.col2)
FROM t
CROSS
JOIN ( SELECT ? AS param FROM DUAL) v
GROUP
BY f( v.param ,t.col2)
MadusankaDの回答によると、過去8年以内に、OracleはJDBCドライバーで同じ名前のバインドパラメーターを再利用し、同等性を維持するためのサポートを追加しました。 (私はそれをテストしていませんが、それが今うまくいくなら、それなら素晴らしいです。)