Saya menyarankan untuk menulis ulang pernyataan sehingga hanya ada satu argumen pengikatan. Pendekatan ini agak jelek, tetapi mengembalikan set hasil:
select max(col1)
, f_col2
from (
select col1
, f(? ,col2) as f_col2
from t
)
group
by f_col2
Pernyataan yang ditulis ulang ini hanya memiliki referensi ke satu argumen pengikatan, jadi sekarang DBMS melihat ekspresi dalam klausa GROUP BY dan daftar SELECT adalah identik.
HTH
[EDIT]
(Saya berharap ada cara yang lebih cantik, inilah mengapa saya lebih memilih pendekatan argumen bernama bind yang digunakan Oracle. Dengan driver Perl DBI, argumen posisi diubah menjadi argumen bernama dalam pernyataan yang sebenarnya dikirim ke Oracle.)
Saya tidak melihat masalahnya pada awalnya, saya tidak mengerti pertanyaan aslinya. (Tampaknya, beberapa orang lain juga melewatkannya.) Tetapi setelah menjalankan beberapa kasus uji, saya sadar apa masalahnya, pertanyaan apa yang berhasil.
Biarkan saya melihat apakah saya dapat menyatakan masalahnya:bagaimana cara mendapatkan dua argumen pengikatan (posisional) yang terpisah untuk diperlakukan (oleh DBMS) seolah-olah itu adalah dua referensi ke argumen pengikatan (bernama) yang sama.
DBMS mengharapkan ekspresi dalam GROUP BY untuk mencocokkan ekspresi dalam daftar SELECT. Tetapi kedua ekspresi dianggap BERBEDA bahkan ketika ekspresinya identik, ketika satu-satunya perbedaan adalah bahwa setiap ekspresi mereferensikan variabel pengikatan yang berbeda. (Kami dapat mendemonstrasikan beberapa kasus uji yang setidaknya diizinkan oleh beberapa DBMS, tetapi ada kasus yang lebih umum yang akan memunculkan pengecualian.)
Pada titik ini jawaban singkatnya adalah, itu membuat saya bingung. Saran yang saya miliki (yang mungkin bukan jawaban sebenarnya untuk pertanyaan awal) adalah menyusun ulang kueri.
[/EDIT]
Saya dapat memberikan detail lebih lanjut jika pendekatan ini tidak berhasil, atau jika Anda memiliki masalah lain untuk mencari tahu. Atau jika ada masalah dengan kinerja (saya dapat melihat pengoptimal memilih rencana yang berbeda untuk kueri yang ditulis ulang, meskipun mengembalikan set hasil yang ditentukan. Untuk pengujian lebih lanjut, kita benar-benar perlu mengetahui DBMS apa, driver apa, statistik, dll.)
EDIT (delapan setengah tahun kemudian)
Upaya lain untuk menulis ulang kueri. Sekali lagi, satu-satunya solusi yang saya buat adalah kueri dengan satu tempat penampung ikatan. Kali ini, kami menempelkannya ke tampilan sebaris yang mengembalikan satu baris, dan menggabungkannya ke t. Saya bisa melihat apa yang dilakukannya; Saya tidak yakin bagaimana pengoptimal Oracle akan melihat ini. Kami mungkin ingin (atau perlu) melakukan konversi eksplisit, mis. TO_NUMBER(?) AS param
, TO_DATE(?,'...') AS param
, TO_CHAR(?) AS param
, tergantung pada tipe data dari parameter bind, dan tipe data yang ingin kita kembalikan seperti dari tampilan.)
Ini adalah bagaimana saya akan melakukannya di MySQL. Kueri asli dalam jawaban saya melakukan operasi gabungan di dalam tampilan sebaris (MySQL tabel turunan ). Dan kami ingin menghindari terwujudnya tabel turunan hughjass jika kami dapat menghindarinya. Kemudian lagi, MySQL mungkin akan membiarkan kueri asli meluncur selama sql_mode
tidak termasuk ONLY_FULL_GROUP_BY
. MySQL juga akan membiarkan kita membuang 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)
Menurut jawaban dari MadusankaD, dalam delapan tahun terakhir, Oracle telah menambahkan dukungan untuk menggunakan kembali parameter bind bernama sama di driver JDBC, dan mempertahankan kesetaraan. (Saya belum mengujinya, tetapi jika itu berhasil sekarang, maka baguslah.)