Manipular condiciones de consulta
#1
Posted 10 November 2012 - 12:32 PM
Resulta que tengo una consulta en Firebird a una sóla tabla y con 6 condiciones en el where los cuales los controlo por medio de parámetros desde Delphi. Lo que espero recibir de la consulta es simplemente si existen registros concordantes o no (al menos 1)... hasta aquí todo bien.
Lo que me tiene dando vueltas la cabeza es que me piden saber, en caso de que la consulta no encuentre ningún registro concordante, cuál o cuáles de los 6 parámetros fue el que hizo que la consulta resultara vacía...
Se me ocurrió ir metiendo parámetro por parámetro de la siguiente manera:
1. Abrir la consulta únicamente con la primera condicion. Si arroja registros, determinar que ese parámetro no afecta la consulta y agregarle otra condición. Si no, quitar la condición de la consulta y determinar que ese parámetro sí afecta a la consulta.
2. Agregar el segundo parámetro y hacer el mismo procedimiento que con el punto 1.
.... y así sucesivamente ...
Aunque creo que sí funcionará mi idea, me parece digamos que... "poco elegante" y quiero saber si existe un método más directo o no tan loco como el que se me ocurrió
Les agradezco su ayuda a todos
Saludox !
#2
Posted 10 November 2012 - 12:40 PM
Seria bueno ver la consulta, aunque parezca vano o los novatos nos gusta ver....
Saludos
#3
Posted 10 November 2012 - 01:19 PM
Imagina los números del 1 al 6 y estas seis condiciones: que no sea el 1, que no sea el 2, y así hasta que no sea el 6.
Si haces tu consulta, no sale ningún número, pero ninguna de las 6 condiciones por sí sola fue la "culpable", como se dice por aquí, todos la mataron y ella sola se murió.
Lo más que podrías obtener que tenga sentido es el mínimo subconjunto de condiciones que da un resultado vacío, pero eso implica probar todas las combinaciones... 2^6 en total, 64, y quedarte con la combinacion que de vacío y tenga el mínimo número de condicones activas. Un lio tremendo.
Una idea más liviana y que no se van a dar cuenta (si no se dieron cuenta de que te pedían un imposible no notarán la diferencia) es buscar condicones indispensables: QUITAS la condición 1 y pruebas con las otras 5, y si deja de ser vacío, esa la marcas como "necesaria". Repites con las demás y tendras las "imprescindibles", que podría no ser ninguna, claro!
#4
Posted 12 November 2012 - 09:30 AM
select count(*)
from ctrac_clasif
where fraccion starting with :fraccion
and num_part = :parte
and cve_impo = :cliente
and cve_prov = :proveedor
and pai_orig = :pais
and imp_exp = :operacion
Si la consulta resultara en 0 me gustaría saber cuál o cuáles condiciones provocaron ese valor
Saludox !
#5
Posted 12 November 2012 - 10:08 AM
#6
Posted 12 November 2012 - 10:15 AM
Yo realmente veo poco útil esto, pero puedes hacerlo con IF EXISTS() con todas las combinaciones en el caso que la consulta principal no retorne resultados.
Puede ser... pero el que paga manda y si es lo suficientemente insistente... pues... qué nos queda ???
Gracias por la sugerencia, qué hace exactamente el IF EXISTS amigo ???
Saludox !
#7
Posted 12 November 2012 - 10:39 AM
Vista la consulta y el nombre de los campos, entiendo que no hay ningún tipo de relación entre ellos. Si así fuera, y dado que son todo "AND", con lanzar 6 consultas (una para condición) tendrías suficiente para saber cuál hace que la query no retorne resultados.
Eso sí, siempre tendrás que comprobar las 6 consultas dado que puede ser una, más de una o todas las condiciones las que provoquen que no retorne resultados.
Nos leemos
#8
Posted 12 November 2012 - 10:55 AM
Este ejemplo es con un StringList, pero en tu caso habría que reemplazarlo por la propiedad SQL de tu consulta, y donde pone "Condicion 1", "Condicion 2", etc ... poner la condicion correspondiente.
var i: Integer; begin with TStringList.Create do try for i:= 0 to $3F do begin Clear; if i and 1 > 0 then Add('Condicion 1'); if i and 2 > 0 then Add('Condicion 2'); if i and 4 > 0 then Add('Condicion 3'); if i and 8 > 0 then Add('Condicion 4'); if i and 16 > 0 then Add('Condicion 5'); if i and 32 > 0 then Add('Condicion 6'); // Aqui ejecutas la consulta y ves si arroja resultados end; finally Free; end; end;
#9
Posted 12 November 2012 - 11:02 AM
1.- Creo una tabla temporal con los siguientes datos:
SELECT COUNT(*)
FROM ctrac_clasif
WHERE fraccion starting WITH :fraccion
2.- Verificar que haya registros en ella, si no los hay: el parámetro fracción afecta la consulta -> fin
3.- Consultamos los datos temporales y así sucesivamente.
SELECT COUNT(*)
FROM tabla_temporal
WHERE num_part = :parte
El objetivo aquí es obtener una muestra a través de una tabla temporal y empezamos a filtrar según los demás parámetros hasta que simplemente encontremos el culpable ó se ejecute sin problemas y esta misma tabla nos devuelva los datos.
Saludos
#10
Posted 12 November 2012 - 11:13 AM
Buenas,
Vista la consulta y el nombre de los campos, entiendo que no hay ningún tipo de relación entre ellos. Si así fuera, y dado que son todo "AND", con lanzar 6 consultas (una para condición) tendrías suficiente para saber cuál hace que la query no retorne resultados.
Eso sí, siempre tendrás que comprobar las 6 consultas dado que puede ser una, más de una o todas las condiciones las que provoquen que no retorne resultados.
Nos leemos
El problema de ésto es que si hago una consulta exclusiva con cada parámetro puede ser que TODAS arrojen resultados, ya que la información si existe en la tabla, pero la combinación AND de todas es la que puede producir que la consulta devuelva un 0, es por eso que si la cosa viene más bien el lado de las combinaciones...
Estoy ideando una solución y probaré las que aquí han propuesto... les platico el resultado
Gracias a todos... sóis los mejores
Saludox !
P.D. Como bien dice mi amigo seoane... no doy por cerrado el hilo, se aceptan más y más ideas
#11
Posted 13 November 2012 - 09:19 AM
¿Porqué no hay chinos en Perú con coleta larga y con un Ferrari azul?
¿porque no hay chinos en Perú? no.
¿porque los chinos no tiene nunca coleta? no.
¿porque sus coletas nunca son largas? no.
¿porque no tienen Ferraris? no.
¿porque jamas compran Ferraris azules? no.
¿Entonces?
Simplemente porque ninguna persona existente cumple con todas las condiciones a la vez, y no hay mucho más que añadir.
Lo más que podrías intentar, como ya te comenté, es a ir eliminando condiciones 1 a 1 hasta que no sea vacío el resultado, y las que desactivaste, esas en su conjunto hacen que no aparezcan resultados: chinos y con ferrari y en Perú, no existen.
Pero si quitas condiciones en otro orden, obtienes otro resultado: en Perú con un ferrari azul no hay nadie.
Encontraras, en general, varias combinaciones que te dan vacío, y ninguna es especial.
Si quieres de todas formas meterte en el lio, yo usaria una SQL de esta forma:
SELECT COUNT(*)
FROM ctrac_clasif
WHERE
((fraccion starting WITH :fraccion) or (:cond1=0))
AND ((num_part = :parte) or (:cond2=0))
AND ((cve_impo = :cliente) or (:cond3=0))
AND ((cve_prov = :proveedor) or (:cond4=0))
AND ((pai_orig = :pais) or (:cond5=0))
AND ((imp_exp = :operacion) or (:cond6=0))
Ahora puedes hacerle un prepare para que sea rápido y probar todas las combinaciones:
Qry.prepare; //Valores iniciales: for i:= 1 to 6 do Qry.Params[i].AsInteger:= 1; //Analizo todas las combinaciones: for i:= 1 to 6 do begin for j=1 downto 0 do begin Qry.Params[i].AsInteger:= j; Qry.EcexQuery; if (Qry.Fields[0].AsInteger = 0) then begin //Esta combinación da vacio, los que están a 1 son los culpables, imprimela o almacenala leyendo los 6 params.values ShowMessage(Qry.Params[1].AsString+' '+Qry.Params[2].AsString+' '+ etc...); end; Qry.close; end; end;
Bueno, el código es "de memoria", algo fallara seguro, pero la idea es que encontraras igual 6 o 7 combinaciones de condiciones "culpables", no hay una condición sola que sea la culpable (igual si, ya es cosa de suerte).