Jump to content
Fórum Script Brasil
  • 0

(Resolvido) Carregando Variáveis Para Tratar No Where


Guest --Alexandre --
 Share

Question

Guest --Alexandre --

Olá,

Preciso usar variáveis para não ter ficar repetindo as subqueries. alguém pode me ajudar?

ex:

o que eu gostaria

select (select max(pg.pagamento) from pagam as pg where ven.codigo = pg.codigo) as PAGAMENTO, ven.codigo as CODIGO where PAGAMENTO is not null

Gostaria de encher o campo PAGAMENTO como se fosse uma variável. Não posso usar a cláusula HAVING pois ela interfere nas funções SUM, MAX, etc... Este foi apenas um exemplo do que preciso. Porem este campo/variável que for preenchido tem que poder ser comparada no where.

Obrigado.

Link to comment
Share on other sites

14 answers to this question

Recommended Posts

  • 0

Olá....

Você pode dar um exemplo do que precisa?

assim: preciso listar os cinco maiores pagamentos feitos aos fornecedores no dia tal...

E um exemplo do que tem?

assim:

datapg, valor, vendedor

14/02/2007 80,00 acme

18/02/2007 120,00 loney tunes

13/03/2007 52,45 wbros

17/04/2007 1,99 cartoonnetwork

29/01/2007 99,88 disney

18/01/2007 100,00 acme

16/04/2007 120,00 fritzlang

07/06/2007 1,99 loney tunes

E um exemplo do resultado esperado?

Link to comment
Share on other sites

  • 0
Guest --Alexandre --

Olá Paulo,

Obrigado pela atenção.

Vou tentar explicar melhor.

Seguinte: Gostaria de encher uma variável para não ficar repetindo uma instrução quando for validar no where ex:

imagina que eu tenho uma função MINHAFUNÇÃO() no Banco de Dados, e nesta função existe vários selects. Daí se eu for usar esta função no SELECT desejado ficar utilizando ela toda hora, vai tomar um tempo maior. Sendo assim, eu queria carregar uma variável já no select e usar a variável ao invés da função. Tentei usar assim:

"select @var := minhafuncao() where @var <> 0" porém não deu certo. Mas seria mais ou menos isso que preciso, senão tenho que usar assim:

"select minhafuncao() where minhafuncao() <> 0" e assim fica lento, porque fico repetindo a função. Também usar o HAVING no meu caso não dá certo.

Entendeu ?

Obrigado.

Alexandre

Link to comment
Share on other sites

  • 0
Guest Visitante

Alexandre, eu só não entendi porque você não entendeu o que o paulobergo pediu...

Mas já que você quer "economizar" o servidor, poderia usar subqueries:

select * from

(select minhafuncao() valoresmaximos) as subquery

where valoresmaximos<>0;

assim, sua "minhafuncao()" será executada so uma vez...

De qualquer forma, tem um moderador aqui (acho que é o micheus) que diz que, com certeza, há outra forma (mais prática e funcional) talvez de fazer o que você precisa...

Vlw?

Link to comment
Share on other sites

  • 0

Olá Visitante,

Obrigado,

Este exemplo que você deu não executa.

Dá erro na execução da query. Mas seria exatamente isso (funcionando) que eu preciso. (carregar o resultado da função ou subquery pra dentro de uma variável e não mais repetir, apenas usar a variável)

Será que o "Micheus" tem a solução mais prática?

Um abraço,

Link to comment
Share on other sites

  • 0

Olá...

Bom... o que falta mesmo é um detalhamento seu...

Por exemplo:

a) Qual é o retorno dessa função MinhaFuncao() , isto é, ela retorna o resultado de uma query, ou seja, uma lista de registros contendo colunas?

B) Se MinhaFuncao() é um "conjunto" de queries, isto pode ser resolvido, realmente, usando-se subqueries, mas se você não especifica (com exemplos) essa função (talvez por não querer compartilhar com ninguém o seu conteúdo), pode colocar, digamos, "exemplos fictícios"... isso ajudaria bastante...

c) Descrever o que precisa (o resultado) e os dados disponíveis, na forma como sugeri antes...

Assim, talvez pudesse ajudar...

Ok?

Link to comment
Share on other sites

  • 0

Olá,

Bom, não coloquei exemplo porque imaginei que não seria preciso. De forma alguma foi com a intenção de esconder algo. Isso não faz parte do meu conceito, uma vez que estou aqui para ser ajudado e também ajudar os outros.

Mas vamos lá.

a function "MinhaFunção" irá retorna 0 ou 1.

vejam o exemplo

////////////////// Função

delimiter $$

CREATE function MinhaFuncao ( cod_cliente )

returns DECIMAL( 1,0 )

deterministic

BEGIN

DECLARE nRetorno DECIMAL(1,0);

DECLARE nAno DECIMAL(4,0);

SELECT max( year(dt_pag) ) into nAno from pagamentos where cod_cliente = pagamentos.cliente ;

if nAno = year( curdate() ) then

SET nRetorno := 1;

else

SET nRetorno := 0;

end if;

return nRetorno;

END $$

////////////////// Fim

Com esta função gostaria de, dentro dos futuros selects, carregar uma variável ao invés de ter que ficar repetindo a função, daí iria ganhar performance ao invés de ficar todo tempo recorrendo a esta função.

Hoje o meu select ta assim:

Select minhafuncao(clientes.codigo), clientes.* from clientes where minhafuncao(clientes.codigo) <> 0

e gostaria de tirar a função do where e testar uma variável se possível.

Se não ficou claro, podem falar que tento explicar melhor.

Um abraço,

Alexandre

Link to comment
Share on other sites

  • 0

Oi, Alexandre!

Estive analisando sua solicitação e, até agora, não consegui visualisar com clareza o que você quer.

Porém, especulando um pouco sobre o que você demonstrou, se sua função "MinhaFuncao" só retorna 0 ou 1, então basta chamá-la apenas uma vez, tal como abaixo, :

Select 1 as diferente_de_zero, clientes.* from clientes where minhafuncao(clientes.codigo) <> 0

Sua sunção não vai retornar valor = 0, por isso não há a necessidade de chamar a função como atributo do select.

Esclareça um pouco mais, e veremos o que pode ser feito.

att

Denis Courcy

Link to comment
Share on other sites

  • 0

Olá Denis

Obrigado por ter respondido.

Seguinte: Este exemplo que dei da função MinhaFuncao() foi apenas um exemplo genérico. A minha necessidade é carregar variáveis no select para não ter que ficar repetido a função ou até mesmo subquerie. Ex:

Hoje to fazendo mais ou menos assim:

select (select......) as valor from produtos where (select.....) > 1000

Gostaria que fosse mais ou menos assim:

select @VARIAVEL := (select.....) from produtos where VARIAVEL > 1000

mais ou menos isto.

Veja bem, não posso usar o HAVING pois preciso fazer o filtro diretamente no WHERE e não no HAVING.

Entendeu ?

Eu dei exemplo com o uso de função anteriormente, mas pode ser qualquer coisa (select, etc). Ou seja, preciso carregar uma variável para não ficar repetindo as instruções/funções

Um abraço,

Alexandre Pereira

Link to comment
Share on other sites

  • 0

Caro Alexandre,

Pelo que conheço do MySQL não há como usar variável na cláusula where a não ser que esta contenha um valor específico.

Exemplo

Set @variavel =1;

select * from cliente where clienteid = @variavel;

que teria como resultado todos os clientes com clienteid = 1.

No seu caso, você está querendo passar uma subquery dinâmica tanto como atributo do select e comparativo da cláusula where.

O mecanismo neste caso é com o uso de uma função. Porém, pelo que entendi o select dentro da função teria que ser dinâmico, ou seja mudaria de tempos em tempos. Este pensamento está correto?

Se sim, o melhor método seria uma execução em separado que geraria um script (arquivo texto com extensão .sql) a cada vez que você fosse alterar o tipo de pesquisa a ser efetuado, ou mesmo a geração deste script na forma de string dentro de sua aplicação.

Vamos continuar avaliando.

att

Denis Courcy

Link to comment
Share on other sites

  • 0

Alexandre,

O que aconteceu aqui é que você estava tentando usar uma variável como macrosubstituição de código. O interpretador do sql não consegue identificar a string dentro da variável como um código (SQL) a ser executado.

Para ganhar performance, avalie quais os atributos mais utilizados em cláusulas where e crie indices para eles.

att Denis Courcy

Caro alexandre

Inconformado com a resposta que te dei anteriormente, busquei no manual do MySQL e encontrei um meio de executar uma macrosubstituição

Na seção 13.2.7 do manual do Mysql 5.0 (página 761)

For prepared statements, you can use placeholders (supported as of MySQL version 5.0.7). The

following statements will return one row from the tbl table:

SET @a=1;

PREPARE TESTE FROM 'SELECT * FROM tbl LIMIT ?';

EXECUTE TESTE USING @a;

podemos fazer assim, também:

SET @MeuSQL = 'SELECT * FROM tbl LIMIT ?';

SET @a=1;

PREPARE TESTE FROM @MeuSQL;

EXECUTE TESTE USING @a;

TESTE = é um pseudodomando (um statement) que será utilizado em substituição a string que tem o comsndo propriamente dito.

@a = neste caso estará substituindo o valor de "?". Assim, Seu Select ficaria assim: SELECT * FROM tbl LIMIT 1';

Ao realizar PREPARE TESTE FROM MeuSQL você estará dizendo ao interpretador que o comando em string dentro de @MeuSQL é um comando e será executado a seguir.

A Linha EXECUTE TESTE USING @a, executa o comando que você programou.

"Prepared execution is an efficient way to execute a statement more than once. The

statement is first parsed to prepare it for execution. Then it is executed one or more times at a later

time, using the statement handle returned by the initialization function.

Prepared execution is faster than direct execution for statements executed more than once, primarily

because the query is parsed only once. In the case of direct execution, the query is parsed every time

it is executed. Prepared execution also can provide a reduction of network traffic because for each

execution of the prepared statement, it is necessary only to send the data for the parameters.

Prepared statements might not provide a performance increase in some situations. For best results,

test your application both with prepared and non-prepared statements and choose whichever yields

best performance.

Another advantage of prepared statements is that it uses a binary protocol that makes data transfer

between client and server more efficient."

Ainda, segundo o manual, os statments a seguir podem ser utilizados como "prepared statements": CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE, e a maioria dos and statements SHOW. Outors statements não são supportados no MySQL 5.0.

Testa e avise se deu certo.

att Denis Courcy

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
 Share

  • Forum Statistics

    • Total Topics
      149.8k
    • Total Posts
      646.6k
×
×
  • Create New...