我建议重新编写语句,以便只有一个绑定参数。这种方法有点难看,但会返回结果集:
select max(col1)
, f_col2
from (
select col1
, f(? ,col2) as f_col2
from t
)
group
by f_col2
这个重写的语句只引用了一个绑定参数,所以现在 DBMS 看到 GROUP BY 子句和 SELECT 列表中的表达式是相同的。
高温高压
[编辑]
(我希望有更漂亮的方式,这就是为什么我更喜欢 Oracle 使用的命名绑定参数方法。使用 Perl DBI 驱动程序,位置参数在实际发送到 Oracle 的语句中转换为命名参数。)
起初我没有看到问题,我不明白原来的问题。(显然,其他几个人也错过了它。)但是在运行了一些测试用例之后,我明白了问题是什么,问题是什么。
让我看看我是否可以说明问题:如何让两个单独的(位置)绑定参数被(由 DBMS)处理,就好像它是对相同(命名)绑定参数的两个引用一样。
DBMS 期望 GROUP BY 中的表达式与 SELECT 列表中的表达式匹配。但是即使表达式相同,这两个表达式也被认为是不同的,唯一的区别是每个表达式引用不同的绑定变量。(我们可以演示一些至少某些 DBMS 允许的测试用例,但还有更一般的情况会引发异常。)
在这一点上,简短的回答是,这让我很难过。我的建议(可能不是对原始问题的实际答案)是重组查询。
[/编辑]
如果这种方法不起作用,或者您在解决它时遇到其他问题,我可以提供更多详细信息。或者如果存在性能问题(我可以看到优化器为重新编写的查询选择不同的计划,即使它返回指定的结果集。为了进一步测试,我们真的需要知道什么 DBMS,什么驱动程序,统计等)
编辑(八年半后)
再次尝试重写查询。同样,我想出的唯一解决方案是带有一个绑定占位符的查询。这一次,我们将它放入一个返回单行的内联视图中,并将其连接到 t。我可以看到它在做什么;我不确定 Oracle 优化器将如何看到这一点。我们可能希望(或需要)进行显式转换,例如TO_NUMBER(?) AS param
, TO_DATE(?,'...') AS param
, TO_CHAR(?) AS param
,具体取决于绑定参数的数据类型,以及我们希望从视图返回的数据类型。)
这就是我在 MySQL 中的做法。我的答案中的原始查询在内联视图(MySQL派生表)中执行连接操作。如果可以避免,我们希望避免实现一个hughjass 派生表。再说一次,只要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 驱动程序中重用相同命名的绑定参数的支持,并保留等效性。(我还没有测试过,但如果它现在有效,那就太好了。)