Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Bases de datos > Firebird e Interbase
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 11-11-2016
ronalg ronalg is offline
Miembro
 
Registrado: may 2003
Ubicación: Sucre - Bolivia
Posts: 68
Poder: 21
ronalg Va por buen camino
Se puede Usar CASE WHEN, IF() O IIF() DENTRO DE LA CLAUSULA WHERE

Muy buenas:

tengo un procedimiento almadenado en firebird que me retorna un cojunto de datos, el procedimiento ya me funciona pero ahora necesito hacer que dicho procedimento "filtre" de acuerdo a un parametro que envio a ella.

Mi pregunta se puede hacer algo así en la sentencia WHERE
Código SQL [-]
select a.codigo, a.numero_cv, a.tipo_transaccion
from tb_compras_ventas a
where
   case
      when :cod_cliente>-1 then a.ref_cliente=:cod_cliente
      when :cod_cliente=-1 then --no hacer nada

talvez sea un disparate pero bueno, la idea es:

Si el parámetro cod_cliente es -1 (Que devuelva todos los registros de todos los clientes)
Si el parámetra cod_cliente es >1 (que devuelva todos los registros de ese cliente)

Mil gracias de antemano
__________________
Saludos desde Sucre - Bolivia
"Si te lo puedes imaginar lo
puedes resolver" Pyriel
Responder Con Cita
  #2  
Antiguo 11-11-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola
Cita:
Empezado por ronalg Ver Mensaje
...
talvez sea un disparate pero bueno, la idea es:

Si el parámetro cod_cliente es -1 (Que devuelva todos los registros de todos los clientes)
Si el parámetra cod_cliente es >1 (que devuelva todos los registros de ese cliente)
Basándome en los campos que mostras en tu código, podrías hacer:
Código SQL [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE SP_TEST (
  COD_CLIENTE INTEGER )
RETURNS (
  R_CODIGO           INTEGER,
  R_NUMERO_CV        INTEGER,
  R_TIPO_TRANSACCION INTEGER )
AS
  DECLARE VARIABLE SENTENCIA VARCHAR(512);
BEGIN
  IF ( COD_CLIENTE = -1 ) THEN
    SENTENCIA = 'SELECT A.CODIGO, A.NUMERO_CV, A.TIPO_TRANSACCION '||
                'FROM TB_COMPRAS_VENTAS A';
  ELSE
    SENTENCIA = 'SELECT A.CODIGO, A.NUMERO_CV, A.TIPO_TRANSACCION '||
                'FROM TB_COMPRAS_VENTAS A' ||
                'WHERE A.REF_CLIENTE = ' || :COD_CLIENTE;

  FOR EXECUTE STATEMENT SENTENCIA
  INTO
    :R_CODIGO,
    :R_NUMERO_CV,
    :R_TIPO_TRANSACCION
  DO
    SUSPEND;
END^

SET TERM ; ^

Ejemplo de uso:
Código SQL [-]
SELECT R_CODIGO, R_NUMERO_CV, R_TIPO_TRANSACCION FROM SP_TEST(6)

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #3  
Antiguo 11-11-2016
ronalg ronalg is offline
Miembro
 
Registrado: may 2003
Ubicación: Sucre - Bolivia
Posts: 68
Poder: 21
ronalg Va por buen camino
Mil gracias por la respueta

Es justamente lo que quiero evitar hacer, pues haría que el código de la consulta dentro del
Código SQL [-]
IF (cod_cliente = -1) then
se repita dos veces y como es una consulta larga y compleja me parece "desperdicio de código" si a eso le sumas que en realidad son dos campos por los cuales debo filtrar la consulta eso implica que el código se repetiría 4 veces.

Por eso estaba interesado en saber si es posible ejecutar partes de una sentencia WHERE en forma condicional, algo así como hacemos con código en Delphi, remplazar, agregar o eliminar una fila de la consulta antes de ejecutarla.

Espero que sea posible, si no la solución que me sugieres sería la única por el momento.

A seguir trabajando..... Y mil gracias (excelente tu ayuda)
__________________
Saludos desde Sucre - Bolivia
"Si te lo puedes imaginar lo
puedes resolver" Pyriel

Última edición por ronalg fecha: 11-11-2016 a las 14:08:38.
Responder Con Cita
  #4  
Antiguo 11-11-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Hola.

Sinceramente no veo manera de hacer lo que consultas en el primer mensaje pero, dependiendo del formato de la sentencia SQL original, se podría optimizar un poco el código anterior del SP para evitar la repetición:
Código SQL [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE SP_TEST (
  COD_CLIENTE INTEGER )
RETURNS (
  R_CODIGO           INTEGER,
  R_NUMERO_CV        INTEGER,
  R_TIPO_TRANSACCION INTEGER )
AS
  DECLARE VARIABLE SENTENCIA VARCHAR(512);
BEGIN
  SENTENCIA = 'SELECT A.CODIGO, A.NUMERO_CV, A.TIPO_TRANSACCION '||
              'FROM TB_COMPRAS_VENTAS A';

  IF ( COD_CLIENTE <> -1 ) THEN
    SENTENCIA = SENTENCIA || 'WHERE A.REF_CLIENTE = ' || :COD_CLIENTE;

  FOR EXECUTE STATEMENT SENTENCIA
  INTO
    :R_CODIGO,
    :R_NUMERO_CV,
    :R_TIPO_TRANSACCION
  DO
    SUSPEND;
END^

SET TERM ; ^
Eso siempre que la sentencia SQL original no sea muy compleja y lo permita...

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #5  
Antiguo 11-11-2016
cloayza cloayza is offline
Miembro
 
Registrado: may 2003
Ubicación: San Pedro de la Paz, Chile
Posts: 910
Poder: 22
cloayza Tiene un aura espectacularcloayza Tiene un aura espectacular
Te propongo lo siguiente

Código SQL [-]
select a.codigo, a.numero_cv, a.tipo_transaccion
from tb_compras_ventas a
where iif(:cod_cliente is null,1,iif(:cod_cliente=a.ref_cliente,1,0))=1

Saludos cordiales
Responder Con Cita
  #6  
Antiguo 11-11-2016
Avatar de ecfisa
ecfisa ecfisa is offline
Moderador
 
Registrado: dic 2005
Ubicación: Tres Arroyos, Argentina
Posts: 10.508
Poder: 36
ecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to beholdecfisa is a splendid one to behold
Cita:
Empezado por cloayza Ver Mensaje
Te propongo lo siguiente
...
Ahí está la opción que no veía...

Saludos
__________________
Daniel Didriksen

Guía de estilo - Uso de las etiquetas - La otra guía de estilo ....
Responder Con Cita
  #7  
Antiguo 11-11-2016
ronalg ronalg is offline
Miembro
 
Registrado: may 2003
Ubicación: Sucre - Bolivia
Posts: 68
Poder: 21
ronalg Va por buen camino
Son unos genios



Sigo intentando procesar que hace pero, funciona.

muchas gracias
__________________
Saludos desde Sucre - Bolivia
"Si te lo puedes imaginar lo
puedes resolver" Pyriel

Última edición por ronalg fecha: 11-11-2016 a las 20:47:15.
Responder Con Cita
  #8  
Antiguo 11-11-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Lo que hace es procesar de forma ineficiente la consulta, aunque logicamente correcto.

Ten en cuenta que SQL es un deficiente lenguaje que no se puede "recomponer" de forma arbitraria. Para eso estan los procedimientos almacenados.
__________________
El malabarista.
Responder Con Cita
  #9  
Antiguo 11-11-2016
ronalg ronalg is offline
Miembro
 
Registrado: may 2003
Ubicación: Sucre - Bolivia
Posts: 68
Poder: 21
ronalg Va por buen camino
Disculpa la neofita pregunta ¿Por qué ineficiente?

Cita:
Empezado por mamcx Ver Mensaje
Lo que hace es procesar de forma ineficiente la consulta, aunque logicamente correcto.

Ten en cuenta que SQL es un deficiente lenguaje que no se puede "recomponer" de forma arbitraria. Para eso estan los procedimientos almacenados.
La verdad no creo enteder que hace realmente el codigo

Cita:
select a.codigo, a.numero_cv, a.tipo_transaccion
from tb_compras_ventas a
where iif(:cod_cliente is null,1,iif(:cod_cliente=a.ref_cliente,1,0))=1
funciona a la prefección pero no logro entenderlo.

mamcx podrias darnos un luz sobre el asunto?
__________________
Saludos desde Sucre - Bolivia
"Si te lo puedes imaginar lo
puedes resolver" Pyriel
Responder Con Cita
  #10  
Antiguo 11-11-2016
Avatar de RONPABLO
[RONPABLO] RONPABLO is offline
Miembro Premium
 
Registrado: oct 2004
Posts: 1.514
Poder: 21
RONPABLO Va por buen camino
Código SQL [-]
select a.codigo, a.numero_cv, a.tipo_transaccion
from tb_compras_ventas a
where
  (:cod_cliente = -1 or a.ref_cliente=:cod_cliente)

el where que te entiendo es el anterior, no hace falta case ni nada más, coloco esos dos entre parentesis para que se solucione como una sola condición pensando que necesites luego agregar un and o algo más.

Respecto a un case en un where sería así:

Código SQL [-]
select a.codigo, a.numero_cv, a.tipo_transaccion
from tb_compras_ventas a
where case when :cod_cliente>-1 then a.ref_cliente  else -1 end = :cod_cliente

Osea, cuando el parametro :cod_cliente sea mayor a -1 manda el valor del campo llamado ref_cliente si no, mande un -1
__________________
"Como pasa el tiempo..... ayer se escribe sin H y hoy con H"
Responder Con Cita
  #11  
Antiguo 11-11-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Cita:
Empezado por ronalg Ver Mensaje
mamcx podrias darnos un luz sobre el asunto?

Debes hacer lo mismo cuando no entiendes el codigo, ejecutarlo paso a paso.

Esta es la parte clave
Código SQL [-]
where iif(:cod_cliente is null,1,iif(:cod_cliente=a.ref_cliente,1,0))=1

Cuando el motor lo recibe, lo sustituye por los valores. Que pasa si lo haces?

Código SQL [-]
where iif(null is null,1)

Lo cual se ejecuta POR CADA FILA DE LA TABLA. Es probable que FB pueda optimizar este caso (no estoy seguro: Hay que chequear el plan de ejecucion)

El problema es con el otro caso:

Código SQL [-]

where iif(false, iif(1=a.ref_cliente,1,0))=1
...
where  iif(True,1,0))=1
where  iif(False,1,0))=1
where  iif(False,1,0))=1
etc...

Estas anulando la posibilidad de usar el indice, porque tiene que chequear fila a fila.

Ves?
__________________
El malabarista.
Responder Con Cita
  #12  
Antiguo 11-11-2016
ronalg ronalg is offline
Miembro
 
Registrado: may 2003
Ubicación: Sucre - Bolivia
Posts: 68
Poder: 21
ronalg Va por buen camino
Muy agradecido mamcx

Ahora entiendo lo que hace el código y tienes razón, pero como dije, esa línea es una de varias en el where de mi consulta creo que vale la pena usarla pues me ahora mucho código, además de que es para el reporte de ventas por DIA o entre fechas o sea que primero recupero los códigos entre un rango de fechas; probare como sube o baja el rendimiento con muchos registros para decidir si usarlo así o en definitiva hacer mas largo el procedimiento almacenado.

RONPABLO muchas gracias lo probé y sorprendentemente (para mi) FUNCIONA tienes razón no era necesario pero estoy seguro que lo aprendido me será útil en otras ocasiones.
__________________
Saludos desde Sucre - Bolivia
"Si te lo puedes imaginar lo
puedes resolver" Pyriel
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
If o Case en cláusula WHERE Jere_84 SQL 6 26-03-2013 23:15:16
Como usar el CASE en 2 SubConsultas ???? AGAG4 Firebird e Interbase 13 17-10-2006 00:08:45
Problemas al usar case David OOP 5 28-07-2006 18:14:19
Case Anidados ¿Se puede? jam888 MS SQL Server 5 31-01-2006 15:39:38
Incluir un IF dentro de un CASE Javi2 SQL 1 21-04-2005 12:59:31


La franja horaria es GMT +2. Ahora son las 11:48:56.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi