Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

É possível usar GROUP BY com variáveis ​​de ligação?


Sugiro reescrever a instrução para que haja apenas um argumento de ligação. Essa abordagem é meio feia, mas retorna o conjunto de resultados:
select max(col1) 
     , f_col2
  from (
         select col1
              , f(? ,col2) as f_col2 
           from t
       )
 group
    by f_col2

Essa instrução reescrita tem uma referência a apenas um único argumento de ligação, então agora o DBMS vê as expressões na cláusula GROUP BY e a lista SELECT são idênticas.

HTH

[EDITAR]

(Gostaria que houvesse uma maneira mais bonita, é por isso que prefiro a abordagem de argumento de ligação nomeado que o Oracle usa. Com o driver Perl DBI, os argumentos posicionais são convertidos em argumentos nomeados na instrução realmente enviada ao Oracle.)

Eu não vi o problema no início, eu não entendi a pergunta original. (Aparentemente, várias outras pessoas também não perceberam.) Mas depois de executar alguns casos de teste, percebi qual era o problema, qual era a pergunta que estava funcionando.

Deixe-me ver se posso expor o problema:como obter dois argumentos de ligação separados (posicionais) a serem tratados (pelo DBMS) como se fossem duas referências ao mesmo argumento de ligação (nomeado).

O DBMS espera que a expressão no GROUP BY corresponda à expressão na lista SELECT. Mas as duas expressões são consideradas DIFERENTES mesmo quando as expressões são idênticas, quando a única diferença é que cada expressão faz referência a uma variável de ligação diferente. (Podemos demonstrar alguns casos de teste que pelo menos alguns DBMS permitirão, mas há casos mais gerais que levantarão uma exceção.)

Neste ponto, a resposta curta é, isso me deixou perplexo. A sugestão que tenho (que pode não ser uma resposta real para a pergunta original) é reestruturar a consulta.

[/EDITAR]

Posso fornecer mais detalhes se essa abordagem não funcionar ou se você tiver algum outro problema para descobrir. Ou se houver um problema com o desempenho (eu posso ver o otimizador escolhendo um plano diferente para a consulta reescrita, mesmo que ele retorne o conjunto de resultados especificado. Para testes adicionais, realmente precisamos saber qual DBMS, qual driver, estatísticas, etc)

EDITAR (oito anos e meio depois)

Outra tentativa de reescrever a consulta. Novamente, a única solução que encontrei é uma consulta com um marcador de posição de vinculação. Desta vez, colocamos em uma visualização em linha que retorna uma única linha e a associamos a t. Eu posso ver o que está fazendo; Não tenho certeza de como o otimizador do Oracle verá isso. Podemos querer (ou precisar) fazer uma conversão explícita, por exemplo. TO_NUMBER(?) AS param , TO_DATE(?,'...') AS param , TO_CHAR(?) AS param , dependendo do tipo de dados do parâmetro de ligação e do tipo de dados que queremos que seja retornado a partir da exibição.)

É assim que eu faria isso no MySQL. A consulta original na minha resposta faz a operação de junção dentro da visualização em linha (MySQL tabela derivada ). E queremos evitar a materialização de uma tabela derivada de hughjass se pudermos evitá-la. Então, novamente, o MySQL provavelmente deixaria a consulta original deslizar enquanto sql_mode não inclui ONLY_FULL_GROUP_BY . O MySQL também nos permitiria eliminar o 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 acordo com a resposta de MadusankaD, nos últimos oito anos, a Oracle adicionou suporte para reutilizar os mesmos parâmetros de ligação nomeados no driver JDBC e manter a equivalência. (Eu não testei isso, mas se isso funcionar agora, então ótimo.)