Club Builder - Foros de discusión Club Builder
Foro de C++Builder en español
 
 FAQFAQ   BuscarBuscar   MiembrosMiembros   Grupos de UsuariosGrupos de Usuarios   RegistrarseRegistrarse 
 PerfilPerfil   Entra para ver tus mensajes privadosEntra para ver tus mensajes privados   EntrarEntrar 

Como realizar una CONSULTA dentro de una CONSULTA?

 
Publicar nuevo tema   Responder al tema    Foros de discusión -> Bases de Datos
Ver tema anterior :: Ver tema siguiente  
Autor Mensaje
Mensaje    Asunto: Como realizar una CONSULTA dentro de una CONSULTA? Responder citando

En mi programa realizo esta consulta dentro de un bucle:
Código:

    for(int N = 110 ; N <= 139; N++)
    {
        int NumeroBoton;
        if(SBArticulos1->Down)
                NumeroBoton = N - 109;
        if(SBArticulos2->Down)
                NumeroBoton = N - 79;
        if(SBArticulos3->Down)
                NumeroBoton = N - 49;
        if(SBComentarios->Down)
                NumeroBoton = N - 19;

        MDatos->IBQuery->SQL->Clear();
        MDatos->IBQuery->SQL->Add( "SELECT TextoBoton,CodigoColor FROM Articulos WHERE "
                                                "ComponenteGrupo =:Parametro1 AND NumeroBoton =:Parametro2");
        MDatos->IBQuery->ParamByName("Parametro1")->AsInteger = ((TSpeedButton*)Sender)->ComponentIndex;
        MDatos->IBQuery->ParamByName("Parametro2")->AsInteger = NumeroBoton;
        MDatos->IBQuery->Open();
        ((TBitBtn*)Components[N])->Caption = MDatos->IBQuery->FieldByName("TextoBoton")->AsString;
        ((TBitBtn*)Components[N])->Font->Color = (TColor) MDatos->IBQuery->FieldByName("CodigoColor")->AsInteger;
    }

Pero en la tabla sobre la que realizo la consulta es fija y tiene 9.000 registros, por lo cual cada vez que llamo a la consulta para localizar 1 solo registro dentro de la tabla tiene que buscar en los 9.000 registros.
Quisiera realizar primero una consulta con el parametro 1, el cual me retornaria solo 120 registros para luego sobre este resultado de consulta ir buscando el parametro 2, de esta forma siempre buscaria el registro final dentro de los 120 registros de la primera consulta. Y así de esta forma creo que el resultado seria mucho mas rapido. En resumen como hago una consulta sobre el resultado de otra consulta? GRACIAS DE ANTEMANO.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Imagino que dependerá de muchas cosas, pero 9000 registros no son en demasié muchos registros, si el campo por el que buscas tiene un indice el cual ayude en la consulta, la verdad es que da igual que busques en los 9000 que en 120, (logicamente habrá diferencias) pero tampoco te pienses que puede merecer el jaleo de codigo para la mejora que vas obtener.

Cuando se quiere un pequeño subconjunto de un conjunto mayor o se quiere permitir la lectura de ciertos campos de una o varias tablas, se suelen utilizar VISTAS, por supuesto, esto tiene sus ventajas y sus inconvenientes.

Pero sinceramente creo que para buscar 1 registro de 9000, si tienes un indice no notarás apenas diferencia o no deberías. Muchos SGBD implementan indices usando ARBOLES BINARIOS BALANCEADOS, fijate que un simple ARBOL DE unos 13 NIVELES da unos 8192 posibles valores y uno de 14 niveles ya pasa a 16.384 posibles nodos, si además el indice es sobre un campo donde no puede haber valores repetidos o esta probabilidad es muy baja, quiere decir que con 13 o 14 comparaciones en el peor caso has encontrado el NODO a buscar. Logicamente no es tan sencillo como esto, pero no te creas tampoco que está muy lejos lo que te digo de ser la realidad...

En fín te deseo suerte, estudia un poco el problema y mira si de verdad merece la pena o vas a ganar poco más de velocidad, como digo tienes la opción de las vistas aunque además de tener sus ventajas/desventajas si vas a crearla para buscar un único campo es tontería, ya te digo quizás no merezca la pena la optimización...

Ciao.
Smile
_________________
OJO!! Ya tenemos subforo de Bases de Datos!!
Gracias a los admins.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor MSN Messenger
Mensaje    Asunto: Responder citando

XyVy tiene toda la razón, no debes hacerte problemas con esa cantidad de datos solo debes crear los indices para "ComponenteGrupo" y "NumeroBoton" dentro de tu base de datos y de esta forma se puede acelerar tu consulta.

Tambien te recomendaría que eches mano de los procedimientos almacenados del Interbase/FireBird esto haria mas transparente tu codigo, y en tu caso solo retornaria un pequeño conjunto de valores los de "N, TextoBoton y CodigoColor" .

Si deseas algunos ejemplos de como usar los procedimientos almacenados envíame un correo a VPRADO@UNSA.EDU.PE
Volver arriba
Ver perfil de usuario Enviar mensaje privado
Mensaje    Asunto: Encontré lo que queria, creo. Responder citando

Gracias a los dos por vuestra contestación. Estoy de acuerdo en que una consulta es muy rápida y que la diferencia de encontrar un registro dado en una tabla de 9.000 o 120 registros es inapreciable. Pero creo que no habéis mirado el código que proponía con atención ya que la búsqueda se ejecutaba 30 veces cada vez que presionaba el botón que tenía que encontrar el registro dado y asignarles sus propiedades a 30 botones que tengo en el programa, pues la consulta se ejecutaba dentro del bucle con 30 repeticiones.

Hasta aquí, me funciona perfectamente, pero claro tengo que tener en cuenta que mi PC es bastante potente (P4-3,2) y mi duda era como se ejecutaría de rápido en otro PC más modesto. En mi PC veía un ligero parpadeo al cambiar de pestaña y asignar nuevos colores y texto a los botones, por lo que pensé que la velocidad estaba bien, pero que si mis ojos eran capaces de ver el parpadeo es porque no era lo suficiente rápido.
La base de datos es INTERBASE 7.1 con dialecto SQL 1, ejecutándose el programa cliente en el mismo PC que el servidor de Base de Datos, y tengo creados índices para el código de artículo y un índice compuesto único para los campos de (ComponenteGrupo, NumeroBoton) con el que realizo las búsquedas que planteo.
Al fin he encontrado otra solución en vez de crear una Vista como me planteabais uno de vosotros.
Esta ha sido por que he encontrado una instrucción en SQL para Interbase y no es otra que el predicado (TOP), pero que no funciona con Interbase ya que es una instrucción de SQL Server u Oracle y me ha traído de cabeza hasta que he descubierto en el libro (La cara Oculta de Delphi 6) que en Interbase se utiliza (ROWS) y (ROWS… TO…) en lugar de TOP.

ROWS para un resultado de un número dado de registros y en compañía de TO para seleccionar rangos de registros devueltos.
Y como los resultados de la consulta en Interbase me los devuelve ordenados por el Índice Activo que es el compuesto, he implementado esta rutina, la cual solo hace una búsqueda cada vez que necesito asignar los textos y color a los 30 botones, mas tarde cuando ya he conseguido la consulta con los 30 registros ordenados, simplemente en el buque for boy asignando los valores a los botones moviéndome con Next.
Los NumeroBoton varían de 1 a 120 dependiendo de la pestaña que el usuario active, pero en cada pestaña solo tengo 30, de ahí que los valores dados a ROWS y TO vallan cambiando según la pestaña activa.
El código que he decidido poner al final, mucho más elegante y legible bajo mí punto de vista es este, y os aseguro que ahora si que es muy, muy rápido, o por lo menos mis ojos ya no pueden ver ese ligero parpadeo sino mas bien aparecen y vuelven a aparecer como si ya estuviesen creados.
Código:

     MDatos->IBQuery->SQL->Clear();
     if(SBArticulos1->Down)
        MDatos->IBQuery->SQL->Add(
        "SELECT TextoBoton,CodigoColor FROM Articulos WHERE ComponenteGrupo =:Parametro1 ROWS 1 TO 30");
     if(SBArticulos2->Down)
        MDatos->IBQuery->SQL->Add(
        "SELECT TextoBoton,CodigoColor FROM Articulos WHERE ComponenteGrupo =:Parametro1 ROWS 31 TO 60");
     if(SBArticulos3->Down)
        MDatos->IBQuery->SQL->Add(
        "SELECT TextoBoton,CodigoColor FROM Articulos WHERE ComponenteGrupo =:Parametro1 ROWS 61 TO 90");
     if(SBComentarios->Down)
        MDatos->IBQuery->SQL->Add(
        "SELECT TextoBoton,CodigoColor FROM Articulos WHERE ComponenteGrupo =:Parametro1 ROWS 91 TO 120");

     MDatos->IBQuery->ParamByName("Parametro1")->AsInteger = ((TSpeedButton*)Sender)->ComponentIndex;
     MDatos->IBQuery->Open();

    for(int N = 110 ; N <= 139; N++)
    {
        ((TBitBtn*)Components[N])->Caption = MDatos->IBQuery->FieldByName("TextoBoton")->AsString;
        ((TBitBtn*)Components[N])->Font->Color = (TColor) MDatos->IBQuery->FieldByName("CodigoColor")->AsInteger;
        MDatos->IBQuery->Next();
    }

Os agradecería que me dierais vuestra opinión al respecto, un saludo a vosotros y todos los del foro, gracias.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: simplificando mas el codigo. Responder citando

Perdón pero esto va por el mensaje de arriba pero mas simplificado. Código final:
Código:

     MDatos->IBQuery->SQL->Clear();
     MDatos->IBQuery->SQL->Add("SELECT TextoBoton,CodigoColor FROM Articulos WHERE ComponenteGrupo =:Parametro1");
     if(SBArticulos1->Down)
        MDatos->IBQuery->SQL->Add(" ROWS 1 TO 30");
     if(SBArticulos2->Down)
        MDatos->IBQuery->SQL->Add(" ROWS 31 TO 60");
     if(SBArticulos3->Down)
        MDatos->IBQuery->SQL->Add(" ROWS 61 TO 90");
     if(SBComentarios->Down)
        MDatos->IBQuery->SQL->Add(" ROWS 91 TO 120");
     MDatos->IBQuery->ParamByName("Parametro1")->AsInteger = ((TSpeedButton*)Sender)->ComponentIndex;
     MDatos->IBQuery->Open();
    for(int N = 110 ; N <= 139; N++)
    {
    ((TBitBtn*)Components[N])->Caption = MDatos->IBQuery->FieldByName("TextoBoton")->AsString;
    ((TBitBtn*)Components[N])->Font->Color = (TColor) MDatos->IBQuery->FieldByName("CodigoColor")->AsInteger;
    MDatos->IBQuery->Next();
    }
Volver arriba
Ver perfil de usuario Enviar mensaje privado Enviar email Visitar sitio web del autor
Mensaje    Asunto: Responder citando

Jesús perdona la verdad es que no me dí cuenta del for, logicamente mejor es obtener todo el resultado en una única consulta que no hacer 120 consultas o las que sean... Las vistas son útiles cuando te quieres construir un subconjunto o conj. intersección de tablas, quizás en tu caso no hubiera sido útil.

Desde Firebird 1.0x nosotros contamos con una clausula parecida a la que comentas SELECT FIRST n SKIP m para obtener ciertos registros del conjunto resultado.

Tu solución es correcta, y me planteo otra posible solucion, si se hay forma de saber que botones les corresponde a cada usuario podías haber usado estos valores en la clausula WHERE y así solo devuelves las que se comprendan entre los valores adecuados para el subconjunto de datos que quieres, o haber hecho un UNION de cada SELECT para cada usuario.

En fín, si te funciona bien va! me alegro que lo hayas solucionado tu mismo. Ciao y cuidate.
_________________
OJO!! Ya tenemos subforo de Bases de Datos!!
Gracias a los admins.
Volver arriba
Ver perfil de usuario Enviar mensaje privado Visitar sitio web del autor MSN Messenger
Mostrar mensajes de anteriores:   
Cambiar a:  
No puedes publicar temas nuevos en este foro
No puedes responder a temas en este foro
No puedes editar tus mensajes en este foro
No puedes borrar tus mensajes en este foro
No puedes votar en las encuestas de este foro


Hosting WordPress Indedmedia desde 3,99 €
© 2002–2026 Club Builder · Funciona con phpBB.