Jeg foreslår, at du omskriver sætningen, så der kun er ét bindeargument. Denne tilgang er lidt grim, men returnerer resultatsættet:
vælg max(col1) , f_col2 from ( vælg col1 , f(? ,col2) som f_col2 fra t ) grupper efter f_col2
Denne omskrevne sætning har kun en reference til et enkelt bindeargument, så nu ser DBMS udtrykkene i GROUP BY-sætningen og SELECT-listen er identiske.
HTH
[EDIT]
(Jeg ville ønske, der var en smukkere måde, det er grunden til, at jeg foretrækker den navngivne bind-argumenttilgang, som Oracle bruger. Med Perl DBI-driveren konverteres positionsargumenter til navngivne argumenter i den sætning, der faktisk sendes til Oracle.)
Jeg så ikke problemet i starten, jeg forstod ikke det oprindelige spørgsmål. (Tilsyneladende gik flere andre mennesker også glip af det.) Men efter at have kørt nogle testcases gik det op for mig, hvad problemet var, hvad spørgsmålet virkede.
Lad mig se, om jeg kan angive problemet:hvordan får man to separate (positionelle) bindeargumenter til at blive behandlet (af DBMS), som om det var to referencer til det samme (navngivne) bindeargument.
DBMS forventer, at udtrykket i GROUP BY matcher udtrykket i SELECT-listen. Men de to udtryk betragtes som FORSKELLIGE, selv når udtrykkene er identiske, når den eneste forskel er, at hvert udtryk refererer til en anden bindingsvariabel. (Vi kan demonstrere nogle testtilfælde, som i det mindste nogle DBMS vil tillade, men der er mere generelle tilfælde, der vil give anledning til en undtagelse.)
På dette tidspunkt er det korte svar, det fik mig til at stå i stå. Det forslag, jeg har (som måske ikke er et egentligt svar på det oprindelige spørgsmål) er at omstrukturere forespørgslen.
[/EDIT]
Jeg kan give flere detaljer, hvis denne tilgang ikke virker, eller hvis du har et andet problem med at finde ud af det. Eller hvis der er et problem med ydeevnen (jeg kan se, at optimeringsværktøjet vælger en anden plan for den omskrevne forespørgsel, selvom den returnerer det angivne resultatsæt. For yderligere test skal vi virkelig vide, hvilket DBMS, hvilken driver, statistik osv.)
REDIGER (otte et halvt år senere)
Endnu et forsøg på en forespørgselsomskrivning. Igen, den eneste løsning, jeg kommer med, er en forespørgsel med én bind-pladsholder. Denne gang sætter vi den ind i en inline-visning, der returnerer en enkelt række, og forbinder den med t. Jeg kan se, hvad den laver; Jeg er ikke sikker på, hvordan Oracle Optimizer vil se dette. Vi ønsker måske (eller har brug for) at lave en eksplicit konvertering, f.eks. TO_NUMBER(?) AS param
, TO_DATE(?,'...') AS param
, TO_CHAR(?) AS param
, afhængigt af datatypen for bindeparameteren og den datatype, vi ønsker skal returneres fra visningen.)
Sådan ville jeg gøre det i MySQL. Den oprindelige forespørgsel i mit svar udfører join-operationen i inline-visningen (MySQL afledt tabel ). Og vi vil undgå at materialisere en hughjass-afledt tabel, hvis vi kan undgå det. Så igen ville MySQL sandsynligvis lade den originale forespørgsel glide så længe som sql_mode
inkluderer ikke ONLY_FULL_GROUP_BY
. MySQL ville også lade os droppe FROM DUAL
)
VÆLG 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)
Ifølge svaret fra MadusankaD har Oracle inden for de seneste otte år tilføjet støtte til genbrug af de samme navngivne bindeparametre i JDBC-driveren og bevarelse af ækvivalens. (Jeg har ikke testet det, men hvis det virker nu, så fantastisk.)