sql >> Base de Datos >  >> RDS >> Oracle

¿Es posible usar GROUP BY con variables de enlace?

Sugiero volver a escribir la declaración para que solo haya un argumento de vinculación. Este enfoque es un poco feo, pero devuelve el conjunto de resultados:

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

Esta declaración reescrita tiene una referencia a un único argumento de vinculación, por lo que ahora el DBMS ve que las expresiones en la cláusula GROUP BY y la lista SELECT son idénticas.

HTH

[EDITAR]

(Desearía que hubiera una forma más bonita, por eso prefiero el enfoque de argumento de vinculación con nombre que utiliza Oracle. Con el controlador DBI de Perl, los argumentos posicionales se convierten en argumentos con nombre en la instrucción que se envía realmente a Oracle).

No vi el problema al principio, no entendí la pregunta original. (Aparentemente, varias otras personas también se lo perdieron). Pero después de ejecutar algunos casos de prueba, me di cuenta de cuál era el problema, cuál era la pregunta que funcionaba.

Déjame ver si puedo plantear el problema:cómo obtener dos argumentos de enlace separados (posicionales) para ser tratados (por el DBMS) como si fueran dos referencias al mismo argumento de enlace (nombrado).

El DBMS espera que la expresión en GROUP BY coincida con la expresión en la lista SELECT. Pero las dos expresiones se consideran DIFERENTES incluso cuando las expresiones son idénticas, cuando la única diferencia es que cada expresión hace referencia a una variable de vinculación diferente. (Podemos demostrar algunos casos de prueba que al menos algunos DBMS permitirán, pero hay casos más generales que generarán una excepción).

En este punto, la respuesta corta es que me tiene perplejo. La sugerencia que tengo (que puede no ser una respuesta real a la pregunta original) es reestructurar la consulta.

[/EDITAR]

Puedo proporcionar más detalles si este enfoque no funciona o si tiene algún otro problema para resolverlo. O si hay un problema con el rendimiento (puedo ver que el optimizador elige un plan diferente para la consulta reescrita, aunque devuelve el conjunto de resultados especificado. Para realizar más pruebas, realmente necesitaríamos saber qué DBMS, qué controlador, estadísticas, etc.)

EDITAR (ocho años y medio después)

Otro intento de reescritura de una consulta. Nuevamente, la única solución que se me ocurre es una consulta con un marcador de posición de enlace. Esta vez, lo colocamos en una vista en línea que devuelve una sola fila y la unimos a t. Puedo ver lo que está haciendo; No estoy seguro de cómo verá esto el optimizador de Oracle. Es posible que queramos (o necesitemos) hacer una conversión explícita, p. TO_NUMBER(?) AS param , TO_DATE(?,'...') AS param , TO_CHAR(?) AS param , según el tipo de datos del parámetro de vinculación y el tipo de datos que queremos que se devuelva desde la vista).

Así es como yo lo haría en MySQL. La consulta original en mi respuesta realiza la operación de unión dentro de la vista en línea (MySQL tabla derivada ). Y queremos evitar materializar una tabla derivada de hughjass si podemos evitarlo. Por otra parte, MySQL probablemente dejaría pasar la consulta original siempre que sql_mode no incluye ONLY_FULL_GROUP_BY . MySQL también nos permitiría eliminar 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)

De acuerdo con la respuesta de MadusankaD, en los últimos ocho años, Oracle ha agregado soporte para reutilizar los mismos parámetros de vinculación con nombre en el controlador JDBC y conservar la equivalencia. (No lo he probado, pero si funciona ahora, genial).