Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > SQL
Registrarse FAQ Miembros Calendario Guía de estilo Temas de Hoy

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 05-05-2005
manos manos is offline
Registrado
 
Registrado: may 2005
Posts: 1
Poder: 0
manos Va por buen camino
es posible este tipo de consulta?

hola a todos...
resulta que la clave primaria de mis registros esta compuesta por dos numeros...
llamemos a estos numeros a y b
estos dos numeros los puedo generar con una formula y con el resultado
otros mas segun un criterio que tengo...
aplicando la formula en iteraciones obtengo un conjunto de pares de numeros que conforman la clave...
por ejemplo (1,2) - (5-7) - (10-20) ...
donde el primer numero seria a y el segundo b

ahora la pregunta es la siguiente :
es posible select REGISTRO from tabla where (a,b) in ({1,2},{5,7},{10,20}) ...?

comento que en este momento
obtengo los resultados de la siguiente forma ...que funciona
select REGISTRO from TABLA where (a=1 and b=2) or (a=5 and b=7) or(a=10 and b=20)...
pero si aumento los numeros la consulta se vuelve muy larga y se incrementan los tiempos de evaluacion...
alguien tendria una consulta mas eficiente ?
Responder Con Cita
  #2  
Antiguo 05-05-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
hasta donde yo sé, (que no sé mucho ), el operador in solo permite un valor, es decir:

where (a in (1,5,10)) and (b in (2,7,20)

pero claro, te traería tambien el (1,7) que no es lo que quieres.

Si dices la base de datos y motor que usas, bde, ado, etc. Igual se podría hacer un algo para traducir a cadenas de texto. No sé si es posible, pero la idea es hacer algo así:
Código Delphi [-]
where ('('+textode(a)+',' + textode(b)+')' in ('(1,2)', '(5,7)', '(10,20)')

Un saludo
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #3  
Antiguo 05-05-2005
Avatar de hermes_32
hermes_32 hermes_32 is offline
Miembro
 
Registrado: jul 2003
Posts: 94
Poder: 22
hermes_32 Va por buen camino
Hola manos,

lo que pides no puede hacerse como dices. Tendrás que ingeniártelas para generar tu query. Me imagino que sabrás cuántos pares de números tienes en el momento de ejecutar la sentencia y sería hacer una cosa más o menos como esta:

Código Delphi [-]
Var vSQL : String;    
...
  vSql := '';
  vSql := 'select REGISTRO from TABLA where 1=1 ';
  //ahora recorres un bucle con todos los pares que tienes
  for i := 1 to Numerodepares do begin
    vSql := vSql + 'And a = ' + QuotedStr(Valor1) + ' and b = ' + QuotedSt(Valor2);
  end;

Más o menos. Que cuánto más pares tienes más va a tardar...eso ya lo sé pero como lo tienes montado no se me ocurre otra cosa.

Un saludo.
Responder Con Cita
  #4  
Antiguo 05-05-2005
lbuelvas lbuelvas is offline
Miembro
 
Registrado: may 2003
Ubicación: Colombia
Posts: 378
Poder: 22
lbuelvas Va por buen camino
Hola foro,

Como me gustan los procedimientos almacenados !.

Me puse en la tarea de hacer un ejercicio completo, espero te sea de utilidad y puedes implementar la idea para tu aplicacion facilmente. El ejemplo esta en Firebird, implementable en Oracle y SQL-Server. No se si se puede hacer con mySQL.

La restriccion UK_CONDICIONES es para evitar que coloques mas de una vez la misma condicion de busqueda.

Se puede definir la tabla condiciones sin el campo id como identificador, si se desea que todas las condiciones en la tabla pasen al procedimiento almacenado. La ventaja con el identificador es que se puede jugar a rangos de condiciones.

Tablas:

CREATE TABLE DATOS (
CAMPO_1 INTEGER NOT NULL,
CAMPO_2 INTEGER NOT NULL,
CAMPO_3 VARCHAR(10) NOT NULL
);

CREATE TABLE CONDICIONES (
ID SMALLINT NOT NULL,
CAMPO_1 INTEGER NOT NULL,
CAMPO_2 INTEGER NOT NULL
);


Restricciones:
ALTER TABLE DATOS ADD CONSTRAINT PK_DATOS PRIMARY KEY (CAMPO_1, CAMPO_2);
ALTER TABLE CONDICIONES ADD CONSTRAINT PK_CONDICIONES PRIMARY KEY (ID);
ALTER TABLE CONDICIONES ADD CONSTRAINT UK_CONDICIONES UNIQUE (CAMPO_1, CAMPO_2);


Datos:
INSERT INTO DATOS (CAMPO_1, CAMPO_2, CAMPO_3) VALUES (1, 2, 'A');
INSERT INTO DATOS (CAMPO_1, CAMPO_2, CAMPO_3) VALUES (5, 7, 'B');
INSERT INTO DATOS (CAMPO_1, CAMPO_2, CAMPO_3) VALUES (10, 20, 'C');
INSERT INTO DATOS (CAMPO_1, CAMPO_2, CAMPO_3) VALUES (10, 7, 'D');
INSERT INTO DATOS (CAMPO_1, CAMPO_2, CAMPO_3) VALUES (10, 1, 'E');
INSERT INTO DATOS (CAMPO_1, CAMPO_2, CAMPO_3) VALUES (5, 1, 'F');
COMMIT WORK;

INSERT INTO CONDICIONES (ID, CAMPO_1, CAMPO_2) VALUES (1, 1, 2);
INSERT INTO CONDICIONES (ID, CAMPO_1, CAMPO_2) VALUES (2, 5, 7);
INSERT INTO CONDICIONES (ID, CAMPO_1, CAMPO_2) VALUES (3, 10, 20);
COMMIT WORK;

El procedimiento:

SET TERM ^ ;

ALTER PROCEDURE SP_SI_ES_POSIBLE (
CONDICION_INICIAL INTEGER,
CONDICION_FINAL INTEGER)
RETURNS (
CAMPO_1 INTEGER,
CAMPO_2 INTEGER,
CAMPO_3 VARCHAR(10))
AS
begin
/* Selecciona el rango de condiciones */
for select campo_1,
campo_2
from condiciones
where id between :condicion_inicial and :condicion_final
into :campo_1,
:campo_2
do begin
/* Busca los registros que cumplan la condicion */
for select campo_3
from datos
where campo_1 = :campo_1
and campo_2 = :campo_2
into campo_3
do begin
suspend;
end
end
end
^

SET TERM ; ^

Como serian las consultas:
Para una condicion (no tendria mucho sentido):
select *
from sp_si_es_posible (2,2);

Todas las condiciones (para tan pocas condiciones es mejor la opcion que colocaste en el foro) :
select *
from sp_si_es_posible (1,3);

Para muchas condiciones (si se te simplificaria el trabajo !!!) :
select *
from sp_si_es_posible (1,50);

Lo anterior suponiendo que tienes 50 condiciones por las cuales buscar.

Muchos exitos.
__________________
Luis Fernando Buelvas T.
Responder Con Cita
  #5  
Antiguo 05-05-2005
lbuelvas lbuelvas is offline
Miembro
 
Registrado: may 2003
Ubicación: Colombia
Posts: 378
Poder: 22
lbuelvas Va por buen camino
Que pena que no sabia colocar etiquetas, ahi va el procedimiento almacenado:

Código SQL [-]
SET TERM ^ ;

ALTER PROCEDURE SP_SI_ES_POSIBLE (
    CONDICION_INICIAL INTEGER,
    CONDICION_FINAL INTEGER)
RETURNS (
    CAMPO_1 INTEGER,
    CAMPO_2 INTEGER,
    CAMPO_3 VARCHAR(10))
AS
begin
  /* Selecciona el rango de condiciones */
  for select campo_1,
             campo_2
      from   condiciones
      where  id between :condicion_inicial and :condicion_final
      into   :campo_1,
             :campo_2
  do begin
    /* Busca los registros que cumplan la condicion */
    for select campo_3
        from   datos
        where  campo_1 = :campo_1
        and    campo_2 = :campo_2
        into   campo_3
    do begin
      suspend;
    end
  end
end
^

SET TERM ; ^
__________________
Luis Fernando Buelvas T.
Responder Con Cita
  #6  
Antiguo 09-05-2005
Avatar de droguerman
droguerman droguerman is offline
Miembro
 
Registrado: abr 2005
Ubicación: tierra
Posts: 999
Poder: 20
droguerman Va por buen camino
si los numeros de tu clave primaria tienen un rango definido podrias probar a multiplicar uno de ellos por un múltiplo de 10 mayor al rango y le sumas el otro campo por ejemplo

Código:
 SELECT REGISTRO FROM tabla 
 where (a*1000)+b  in ( 1002, 5007, 10020);
Responder Con Cita
  #7  
Antiguo 09-05-2005
Avatar de Lepe
[Lepe] Lepe is offline
Miembro Premium
 
Registrado: may 2003
Posts: 7.424
Poder: 29
Lepe Va por buen camino
Me ha gustado mucho la idea de droguerman

ea, queda dicho.

Un saludo
__________________
Si usted entendió mi comentario, contácteme y gustosamente,
se lo volveré a explicar hasta que no lo entienda, Gracias.
Responder Con Cita
  #8  
Antiguo 09-05-2005
lbuelvas lbuelvas is offline
Miembro
 
Registrado: may 2003
Ubicación: Colombia
Posts: 378
Poder: 22
lbuelvas Va por buen camino
Hola foro,

Parece que la solucion que sugerí requiere mucha elaboracion, la solucion de droguerman es completamente aplicable si el numero de registros no es alto, ya que el plan del motor de base de datos (cualquiera que sea) sería recorrer la tabla de manera natural (de comienzo a fin).

Otra posible solucion y siquiendo un poco la linea de droguerman es crear un campo fisico en la BD (campo_auxiliar) y que puede ser mantenido por triggers (before insert y before update) con la formula de droguerman. El campo deberia estar indexado, por aquello del rendimiento que tanto me preocupa.


campo_auxiliar = (a*1000) + b;

y la consuta

SELECT REGISTRO FROM tabla
where campo_auxiliar in ( 1002, 5007, 10020);
__________________
Luis Fernando Buelvas T.
Responder Con Cita
Respuesta



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


La franja horaria es GMT +2. Ahora son las 02:33:53.


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