sql >> Database >  >> RDS >> Oracle

Is het mogelijk om GROUP BY te gebruiken met bindvariabelen?

Ik stel voor de verklaring te herschrijven zodat er maar één bind-argument is. Deze benadering is nogal lelijk, maar geeft de resultaatset terug:

select max(col1) 
     , f_col2
  from (
         select col1
              , f(? ,col2) as f_col2 
           from t
       )
 group
    by f_col2

Deze herschreven instructie heeft een verwijzing naar slechts één bind-argument, dus nu ziet het DBMS dat de expressies in de GROUP BY-clausule en de SELECT-lijst identiek zijn.

HTH

[BEWERKEN]

(Ik wou dat er een mooiere manier was, daarom geef ik de voorkeur aan de benoemde bind-argumentbenadering die Oracle gebruikt. Met de Perl DBI-driver worden positionele argumenten omgezet in benoemde argumenten in de instructie die daadwerkelijk naar Oracle wordt verzonden.)

Ik zag het probleem eerst niet, ik begreep de oorspronkelijke vraag niet. (Blijkbaar hebben verschillende andere mensen het ook gemist.) Maar na wat testcases te hebben uitgevoerd, drong het tot me door wat het probleem was, wat de vraag werkte.

Eens kijken of ik het probleem kan noemen:hoe krijg ik twee afzonderlijke (positionele) bind-argumenten die (door de DBMS) worden behandeld alsof het twee verwijzingen zijn naar hetzelfde (benoemde) bind-argument.

Het DBMS verwacht dat de expressie in de GROUP BY overeenkomt met de expressie in de SELECT-lijst. Maar de twee expressies worden als VERSCHILLEND beschouwd, zelfs als de expressies identiek zijn, als het enige verschil is dat elke expressie verwijst naar een andere bindvariabele. (We kunnen enkele testgevallen demonstreren die op zijn minst sommige DBMS zullen toestaan, maar er zijn meer algemene gevallen die een uitzondering zullen opleveren.)

Op dit punt is het korte antwoord, dat heeft me stumped. De suggestie die ik heb (die misschien geen echt antwoord op de oorspronkelijke vraag is) is om de zoekopdracht te herstructureren.

[/EDIT]

Ik kan meer details geven als deze aanpak niet werkt, of als je een ander probleem hebt om het uit te zoeken. Of als er een probleem is met de prestaties (ik zie dat de optimizer een ander plan kiest voor de herschreven query, ook al retourneert deze de gespecificeerde resultatenset). Voor verdere tests moeten we echt weten welke DBMS, welk stuurprogramma, statistieken, enz.)

BEWERKEN (acht en een half jaar later)

Nog een poging tot herschrijven van een query. Nogmaals, de enige oplossing die ik bedenk, is een query met één tijdelijke aanduiding voor binden. Deze keer plakken we het in een inline-weergave die een enkele rij retourneert, en voegen we die toe aan t. Ik kan zien wat het doet; Ik weet niet zeker hoe de Oracle-optimizer dit zal zien. We willen (of moeten) misschien een expliciete conversie doen, b.v. TO_NUMBER(?) AS param , TO_DATE(?,'...') AS param , TO_CHAR(?) AS param , afhankelijk van het datatype van de bindparameter en het datatype dat we willen teruggeven vanuit de view.)

Dit is hoe ik het zou doen in MySQL. De oorspronkelijke query in mijn antwoord voert de join-bewerking uit in de inline-weergave (van MySQL afgeleide tabel ). En we willen voorkomen dat er een van hughjass afgeleide tabel wordt gemaakt als we die kunnen vermijden. Aan de andere kant zou MySQL waarschijnlijk de oorspronkelijke query laten schuiven zolang sql_mode omvat niet ONLY_FULL_GROUP_BY . MySQL zou ons ook de mogelijkheid geven om de 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)

Volgens het antwoord van MadusankaD heeft Oracle in de afgelopen acht jaar ondersteuning toegevoegd voor het hergebruik van bindparameters met dezelfde naam in het JDBC-stuurprogramma en het behouden van gelijkwaardigheid. (Ik heb dat niet getest, maar als dat nu werkt, prima.)



  1. Uitstelbare beperkingen in SQL Server

  2. Hoe maak je een MySql-database met shell_exec php?

  3. Hoe kan ik zoeken in een tabel met door komma's gescheiden waarden?

  4. Vervolgkeuzelijst met samenvoegquery