Я предлагаю переписать утверждение так, чтобы был только один аргумент связывания.
Этот подход несколько уродлив, но возвращает набор результатов:
select max(col1)
, f_col2
from (
select col1
, f(? ,col2) as f_col2
from t
)
group
by f_col2
Это переписанное утверждение имеет ссылку только на один аргумент связывания, поэтому теперь СУБД видит выражения в предложении GROUP BY и список SELECT идентичны.
НТН
[EDIT]
(Хотелось бы, чтобы был более красивый способ, поэтому я предпочитаю подход с именованным аргументом связывания, который использует Oracle. С драйвером Perl DBI позиционные аргументы преобразуются в именованные аргументы в операторе, фактически отправленном в Oracle.)
Сначала я не видел проблемы, я не понял исходного вопроса. (Очевидно, некоторые другие тоже пропустили это.) Но после выполнения некоторых тестов, я понял, в чем проблема, в чем заключался вопрос.
Позвольте мне посмотреть, могу ли я сформулировать проблему: как получить два отдельных (позиционных) аргумента связывания, которые должны обрабатываться (СУБД), как если бы это были две ссылки на один (именованный) аргумент связывания.
СУБД ожидает, что выражение в GROUP BY совпадет с выражением в списке SELECT. Но два выражения считаются РАЗЛИЧНЫМИ, даже если выражения идентичны, когда единственное отличие состоит в том, что каждое выражение ссылается на другую переменную связывания. (Мы можем продемонстрировать некоторые тестовые случаи, которые по крайней мере некоторые СУБД позволят, но есть более общие случаи, которые вызовут исключение.)
На данный момент короткий ответ: это поставило меня в тупик. У меня есть предложение (которое может не являться фактическим ответом на исходный вопрос) - реструктурировать запрос.
[/ EDIT]
Я могу предоставить более подробную информацию, если этот подход не работает, или если у вас есть другие проблемы с его выяснением. Или, если есть проблема с производительностью (я вижу, как оптимизатор выбирает другой план для переписанного запроса, даже если он возвращает указанный набор результатов. Для дальнейшего тестирования нам действительно нужно знать, какая СУБД, какой драйвер, статистика и пр.)
РЕДАКТИРОВАТЬ (восемь с половиной лет спустя)
Еще одна попытка переписать запрос. Опять же, единственное решение, которое я придумаю, это запрос с одним заполнителем привязки. На этот раз мы вставляем его во встроенное представление, которое возвращает одну строку, и присоединяем его к t. Я вижу, что он делает; Я не уверен, как оптимизатор Oracle увидит это. Мы можем захотеть (или нам нужно) сделать явное преобразование, например, TO_NUMBER(?) AS param
, TO_DATE(?,'...') AS param
, TO_CHAR(?) AS param
, в зависимости от типа данных параметра bind и типа данных, который мы хотим вернуть из представления.)
Вот как бы я это сделал в 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 параметров с одинаковыми именами и сохранения эквивалентности. (Я не проверял это, но если это работает сейчас, тогда отлично.)