Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Problemas con Operador Or (https://www.clubdelphi.com/foros/showthread.php?t=33930)

lucasarts_18 20-07-2006 23:03:29

Problemas con Operador Or
 
Hola a todos:

Tengo la siguiente consulta SQL:

Código SQL [-]
SELECT NOM.*, SEG.COD_ESTADO_SEG FROM 
PRF_NOMBRAMIENTO NOM,
PRF_SEGUIMIENTO SEG
WHERE NOM.ANO_ACADEMICO = SEG.ANO_ACADEMICO
  AND NOM.COD_ESCUELA = SEG.COD_ESCUELA
  AND NOM.COD_NOMBRA = SEG.COD_NOMBRA
  AND (SEG.COD_ESTADO_SEG = 1
        OR SEG.COD_ESTADO_SEG BETWEEN 1 AND 2)
  AND SEG.ESTADO = 'VIGENTE'

pero siempre me toma los valores del OR :mad:

Si a la primera instrucción le paso un valor inexistente solo en ese momento debería saltar al operador OR.
Espero que se entienda, Mil Gracias

vtdeleon 20-07-2006 23:32:12

Cita:

Si a la primera instrucción le paso un valor inexistente
Cual 1ra instruccion. Solo veo una sola sentencia:confused:

Cita:

Espero que se entienda, Mil Gracias
Eeesteee, NOP:confused:

lucasarts_18 20-07-2006 23:48:04

Amigo VtDeleon, tengo entendido que el operador OR se evalua de todas maneras si la primera expresión es verdadera.

Lo que yo necesito es algo así.

1 = Documento Ingresado
2 = Docuemnto Enviado
y Ademas debe tener la opción de traer ambos o sea uno y dos

Entonces:

Código SQL [-]
AND (SEG.COD_ESTADO_SEG = 1 Aquí puede ser un valor inexistente, por ejemplo ya le envio un -1
  OR SEG.COD_ESTADO_SEG BETWEEN 1 AND 2)

Por lo tanto -1 yo sé que no existe tal registro lo que debería
recuperar todos los documentos que tengan 1 y 2.
El problema se produce cuando la primera expresión evalua a verdadera me recupera registro que tenga coincidencia con el numero 2, esto no debería pasar ya que está en el OR, pero insisto creo que el OR también se produce si la primera expresión es verdadera.

delphi.com.ar 20-07-2006 23:58:58

Cita:

Empezado por lucasarts_18
Amigo VtDeleon, tengo entendido que el operador OR se evalua de todas maneras si la primera expresión es verdadera.

Desconozco si el ANSI SQL define si las evaluaciones son por circuito corto o largo. Pero si no me equivoco (no quiero asegurarlo), motores como Oracle realiza las evaluaciones derecha a izquierda (de abajo hacia arriba).

Cita:

Empezado por lucasarts_18
El problema se produce cuando la primera expresión evalua a verdadera me recupera registro que tenga coincidencia con el numero 2, esto no debería pasar ya que está en el OR, pero insisto creo que el OR también se produce si la primera expresión es verdadera.

El OR es verdadero cuando cualquiera de las dos expresiones son verdaderas... ¿Cómo llegas a saber que esta haciendo las dos evaluaciones?

lucasarts_18 21-07-2006 00:08:26

Cita:

Empezado por delphi.com.ar
Desconozco si el ANSI SQL define si las evaluaciones son por circuito corto o largo. Pero si no me equivoco (no quiero asegurarlo), motores como Oracle realiza las evaluaciones derecha a izquierda (de abajo hacia arriba).

Uso Oracle y probaré invertiendo la situación

Cita:

Empezado por delphi.com.ar
El OR es verdadero cuando cualquiera de las dos expresiones son verdaderas...

Esto es cierto, ví la tabla de Boolena en un manual de Oracle.

Cita:

Empezado por delphi.com.ar
¿Cómo llegas a saber que esta haciendo las dos evaluaciones?

Porque si la primera expresión es verdadera me trae registros de documentos que tienen asignado un seguimiento 2 (es decir enviado), por lo tanto ahí yo sé que trae registro después del or

vtdeleon 21-07-2006 00:16:35

Creo saber por que te sale asi.

(Soy un CHUTO explicando pero ahi vamos...)
Segun mi interpretacion estas diciendo que traiga cada registro que cumpla "EG.COD_ESTADO_SEG = 1", si ese registro no cumpel con esa condicion pues con esta ==> SEG.COD_ESTADO_SEG between 1 and 2"

Si evaluas registro por registro veras qeu va a traer tando 1 como 2.

delphi.com.ar 21-07-2006 00:26:14

Cita:

Empezado por lucasarts_18
Uso Oracle y probaré invertiendo la situación

No te entiendo.. en un OR de este tipo, si inviertes la situación no ganas nada. Si fuera en Delphi y hubieras compilado ese fragmento de código con Short Circuit como es por defecto, y ambos “comparandos” son funciones, podría decirte que si es importante el orden, para evitar ejecutar el código de una de ellas. Pero en este caso no se que es lo que te afecta que se compare una u otra.

Cita:

Empezado por lucasarts_18
Porque si la primera expresión es verdadera me trae registros de documentos que tienen asignado un seguimiento 2 (es decir enviado), por lo tanto ahí yo sé que trae registro después del or

No era a eso lo que me refería.... cómo sabes que ejecutó las dos??.. Obviamente si tienes el valor, una de las dos es cierta y en algo tan excluyente como esto, es fácil saber cuál de las dos!

lucasarts_18 21-07-2006 00:27:00

Cita:

Empezado por vtdeleon
Creo saber por que te sale asi.

(Soy un CHUTO explicando pero ahi vamos...)
Segun mi interpretacion estas diciendo que traiga cada registro que cumpla "EG.COD_ESTADO_SEG = 1", si ese registro no cumpel con esa condicion pues con esta ==> SEG.COD_ESTADO_SEG between 1 and 2"

Es exactamente eso

Cita:

Empezado por vtdeleon
Si evaluas registro por registro veras qeu va a traer tando 1 como 2.

[/quote=vtdeleon]

Si yo quito la segunda expresión, es decir el Or, me devuelva los registro que cumplen la condición 1, la idea es que si yo entrego un valor inexistente (lo hago de forma adrede a través de la aplicación) me devuelva registros que contenga 1 y 2

ContraVeneno 21-07-2006 00:47:50

en la sentencia:
Código SQL [-]
where Campo = 1 
or Campo between 1 and 2

de nada te sirve tener "Campo = 1" porque de igual manera se esta haciendo la misma comparación en el "between 1". Al poner :
"between 1 and 2"
es lo mismo que si pusieras:
"campo = 1 or Campo=2"

y al utilizar el operador Or, es como si solo estuvieras evaluando el between. Es decir, a mi parecer, la instrucción anterior, daría exactamente los mismo resultados que

Código SQL [-]
where Campo between 1 and 2

Cualquier valor diferente de 1 ó 2, no se mostrará como resultado de la consulta.

lucasarts_18 21-07-2006 00:55:42

Cita:

Short-Circuit Evaluation
When evaluating a logical expression, PL/SQL uses short-circuit evaluation. That is,
PL/SQL stops evaluating the expression as soon as the result can be determined.
This lets you write expressions that might otherwise cause an error. Consider the
following OR expression:
DECLARE
...
on_hand INTEGER;
on_order INTEGER;
BEGIN
..
IF (on_hand = 0) OR ((on_order / on_hand) < 5) THEN
...
END IF;
END;
When the value of on_hand is zero, the left operand yields TRUE, so PL/SQL need
not evaluate the right operand. If PL/SQL were to evaluate both operands before
applying the OR operator, the right operand would cause a division by zero error. In
any case, it is a poor programming practice to rely on short-circuit evaluation.
lo que yo entiendo de esto es que cuando la evalución de izquierda es verdadera PL/SQL no necesita evaluar datos de la parte derecha por lo tanto debería traerme solo los registros de coincidan con el valor 1.

Hasta Luego y gracias por su atención

delphi.com.ar 21-07-2006 00:59:22

Cita:

Empezado por lucasarts_18
Si yo quito la segunda expresión, es decir el Or, me devuelva los registro que cumplen la condición 1, la idea es que si yo entrego un valor inexistente (lo hago de forma adrede a través de la aplicación) me devuelva registros que contenga 1 y 2

Ahora entiendo otra cosa...

Por un lado quieres obtener:
Código SQL [-]
SELECT NOM.*, SEG.COD_ESTADO_SEG 
FROM PRF_NOMBRAMIENTO NOM, PRF_SEGUIMIENTO SEG
WHERE NOM.ANO_ACADEMICO = SEG.ANO_ACADEMICO
    AND NOM.COD_ESCUELA = SEG.COD_ESCUELA
    AND NOM.COD_NOMBRA = SEG.COD_NOMBRA
    AND SEG.COD_ESTADO_SEG BETWEEN 1 AND 2

Pero cuando no se cumple esa relación quieres que la relación se establezca con los vigentes?...

yo pondría un "OR NOT EXISTS (RELACIÓN) AND ESTADO = 'VIGENTE'"

Mick 21-07-2006 04:38:33

Estas mezclando dos conceptos diferentes, que se evalue o no la segunda comparacion es un tema de optimizacion del compilador o interprete que sea, una optimizacion permite simplemente que el codigo se ejecute un poco mas rapido, pero esto no tiene nada que ver con el resultado, es decir
el resultado de una comparacion o consulta va a ser el mismo independientemente de que se evaluen los dos resultados o no.

Si hacemos "A o B", y al interpretar el resultado vemos que A es VERDADERO podriamos evaluar B o no, pero ya sabemos que el resultado final va a ser VERDADERO valga lo que valga B, de modo que muchos compiladores por tema de acelerar la ejecucion y no hacer comprobaciones superfluas, siemplemente ahi paran y ya no evaluan B porque no hace falta, ya sabemos que el resultado final es VERDADERO independientemente de lo que valga B.

La explicacion en ingles de "Short-Circuit Evaluation", no tiene que ver con que los resultados en tu caso vayan a ser diferentes, has interpretado mal esa explicacion.

Ese texto se limita a explicar un caso muy concreto que de rebote produce el hecho de no evaluar B, y es que si en B existe una operacion matematica que puede dar error (como una division por cero), en el caso de short-circuit evaluation si A ya es verdadero, la operacion B no daria error porque B no se evalua. No es que de resultados distintos es que se pararia el programa con un error o excepcion de division por cero en el caso de que se evaluase B.

Pero este es un caso "extremo" por asi decirlo que no tiene que ver con la logica del operador OR, en definitiva un OR es un OR y siempre dara el mismo resultado independientemente de que el compilador o el interprete lo procesen de una forma u otra.

Saludos

vtdeleon 22-07-2006 00:51:51

Yo enteindo que Si ejecutamos la consulta y no obtenemos por lo menos un registro qeu cumpla con la condicion "SEG.COD_ESTADO_SEG = 1", pues evalue "SEG.COD_ESTADO_SEG between 1 and 2 " (aunque no entiendo por que between 1 and 2 si 1 ha sido evaluado anteriormente:confused:)

Es asi lucarsart?

lucasarts_18 22-07-2006 03:18:35

He encontrado la solución
 
Hola Amigos:

Aquí logre sacar los resultados deseados:




Código SQL [-]
SELECT NOM.*, SEG.COD_ESTADO_SEG FROM PRF_NOMBRAMIENTO 
NOM,PRF_SEGUIMIENTO SEG
WHERE NOM.ANO_ACADEMICO = SEG.ANO_ACADEMICO  
AND NOM.COD_ESCUELA = SEG.COD_ESCUELA  
AND NOM.COD_NOMBRA = SEG.COD_NOMBRA  
AND ((SEG.COD_ESTADO_SEG = I_OPCION)        
  OR (I_OPCION = - 1 AND SEG.COD_ESTADO_SEG BETWEEN 1 AND 2)) 
AND SEG.ESTADO = 'VIGENTE'

I_OPCION = PARAMETRO

Con esto mi reporte está funcionando a la perfección, gracias a todos los que intentaron orientarme :)

Hasta luego -

lucasarts_18 22-07-2006 03:23:21

Cita:

Empezado por vtdeleon
Yo enteindo que Si ejecutamos la consulta y no obtenemos por lo menos un registro qeu cumpla con la condicion "SEG.COD_ESTADO_SEG = 1", pues evalue "SEG.COD_ESTADO_SEG between 1 and 2 " (aunque no entiendo por que between 1 and 2 si 1 ha sido evaluado anteriormente:confused:)

Es asi lucarsart?

No tan así, puse el SQL de la solución, basicamente si yo mando un valor 1 me devuelva todas las coincidencias y si mando un valor 2 me devuelva esas coincidencias y, para terminar si mando un -1 me mande los registros que coincidan con los valores 1 y 2, espero que se entienda :(

Hasta Luego -


La franja horaria es GMT +2. Ahora son las 16:32:12.

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