Предлагам да пренапишете израза, така че да има само един свързващ аргумент. Този подход е някак грозен, но връща резултатния набор:
select max(col1)
, f_col2
from (
select col1
, f(? ,col2) as f_col2
from t
)
group
by f_col2
Този пренаписан оператор има препратка към само един аргумент за свързване, така че сега СУБД вижда изразите в клаузата GROUP BY и списъкът SELECT са идентични.
HTH
[РЕДАКТИРАНЕ]
(Иска ми се да има по-красив начин, ето защо предпочитам подхода на именуван свързващ аргумент, който Oracle използва. С Perl DBI драйвера позиционните аргументи се преобразуват в именувани аргументи в израза, действително изпратен на Oracle.)
Първоначално не видях проблема, не разбрах първоначалния въпрос. (Очевидно няколко други хора също са го пропуснали.) Но след като пуснах някои тестови случаи, ми просветна какъв е проблемът, какъв въпрос работи.
Нека да видя дали мога да заявя проблема:как да накарам два отделни (позиционни) аргумента за свързване да бъдат третирани (от СУБД) като че ли са две препратки към един и същ (наименуван) аргумент за свързване.
СУБД очаква изразът в GROUP BY да съответства на израза в списъка SELECT. Но двата израза се считат за РАЗЛИЧНИ дори когато изразите са идентични, когато единствената разлика е, че всеки израз препраща към различна свързваща променлива. (Можем да демонстрираме някои тестови случаи, които поне някои СУБД ще позволят, но има по-общи случаи, които ще предизвикат изключение.)
На този етап краткият отговор е, че това ме озадачи. Предложението, което имам (което може да не е действителен отговор на първоначалния въпрос) е да преструктурираме заявката.
[/РЕДАКТИРАНЕ]
Мога да предоставя повече подробности, ако този подход не работи или ако имате някакъв друг проблем да го разберете. Или ако има проблем с производителността (виждам как оптимизаторът избира различен план за пренаписаната заявка, въпреки че връща указания набор от резултати. За по-нататъшно тестване наистина трябва да знаем каква СУБД, какъв драйвер, статистика и др.)
РЕДАКТИРАНЕ (осем години и половина по-късно)
Още един опит за пренаписване на заявка. Отново, единственото решение, което измислям, е заявка с един контейнер за свързване. Този път го поставяме във вграден изглед, който връща един ред, и го присъединяваме към 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 през последните осем години Oracle е добавил поддръжка за повторно използване на същите именувани параметри за свързване в JDBC драйвера и запазване на еквивалентността. (Не съм тествал това, но ако работи сега, тогава е страхотно.)