sql >> Databasteknik >  >> RDS >> Oracle

Är det möjligt att använda GROUP BY med bindningsvariabler?

Jag föreslår att du skriver om uttalandet så att det bara finns ett bindningsargument. Det här tillvägagångssättet är lite fult, men returnerar resultatet:

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

Denna omskrivna sats har en referens till endast ett enda bindningsargument, så nu ser DBMS uttrycken i GROUP BY-satsen och SELECT-listan är identiska.

HTH

[EDIT]

(Jag önskar att det fanns ett snyggare sätt, det är därför jag föredrar den namngivna bindningsargumentmetoden som Oracle använder. Med Perl DBI-drivrutinen konverteras positionsargument till namngivna argument i uttalandet som faktiskt skickas till Oracle.)

Jag såg inte problemet först, jag förstod inte den ursprungliga frågan. (Tydligen har flera andra personer missat det också.) Men efter att ha kört några testfall gick det upp för mig vad problemet var, vad frågan fungerade.

Låt mig se om jag kan ange problemet:hur man får två separata (positionella) bindningsargument att behandlas (av DBMS) som om det vore två referenser till samma (namngivna) bindningsargument.

DBMS förväntar sig att uttrycket i GROUP BY ska matcha uttrycket i SELECT-listan. Men de två uttrycken anses OLIKA även när uttrycken är identiska, när den enda skillnaden är att varje uttryck refererar till en annan bindningsvariabel. (Vi kan visa några testfall som åtminstone vissa DBMS tillåter, men det finns mer allmänna fall som ger upphov till ett undantag.)

Vid det här laget är det korta svaret, det fick mig att häpna. Förslaget jag har (som kanske inte är ett faktiskt svar på den ursprungliga frågan) är att strukturera om frågan.

[/EDIT]

Jag kan ge mer information om det här tillvägagångssättet inte fungerar, eller om du har något annat problem med att ta reda på det. Eller om det finns ett problem med prestanda (jag kan se att optimeraren väljer en annan plan för den omskrivna frågan, även om den returnerar den angivna resultatuppsättningen. För ytterligare testning skulle vi verkligen behöva veta vilken DBMS, vilken drivrutin, statistik, etc.)

REDIGERA (åtta och ett halvt år senare)

Ännu ett försök att skriva om en fråga. Återigen, den enda lösningen jag kommer på är en fråga med en bindningsplatshållare. Den här gången fäster vi den i en inline-vy som returnerar en enstaka rad och ansluter den till t. Jag kan se vad den gör; Jag är inte säker på hur Oracle-optimeraren kommer att se detta. Vi kanske vill (eller behöver) göra en explicit konvertering t.ex. TO_NUMBER(?) AS param , TO_DATE(?,'...') AS param , TO_CHAR(?) AS param , beroende på datatypen för bindningsparametern och datatypen vi vill ska returneras från vyn.)

Så här skulle jag göra i MySQL. Den ursprungliga frågan i mitt svar gör joinoperationen i inline-vyn (MySQL härledd tabell ). Och vi vill undvika att materialisera en hughjass-härledd tabell om vi kan undvika det. Återigen, MySQL skulle förmodligen låta den ursprungliga frågan glida så länge som sql_mode inkluderar inte ONLY_FULL_GROUP_BY . MySQL skulle också låta oss släppa 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)

Enligt svaret från MadusankaD har Oracle under de senaste åtta åren lagt till stöd för att återanvända samma namngivna bindningsparametrar i JDBC-drivrutinen, och bibehålla ekvivalens. (Jag har inte testat det, men om det fungerar nu, så bra.)



  1. Hitta tabell med maximalt antal rader i en databas i mysql

  2. Uppdatera fält när inte null

  3. Mysql-fråga med Left Join är för mycket långsam

  4. SQL-fråga med ON DUPLICATE KEY UPDATE förtydligande behövs