Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Mirar por favor este query y comentar... (https://www.clubdelphi.com/foros/showthread.php?t=61525)

El_Raso 11-11-2008 16:21:14

Mirar por favor este query y comentar...
 
Código SQL [-]
SELECT
    A.NUMEROFICHA,
    A.NOMBREJEFE,
    A.APODOJEFE,
    A.CALLE,
    A.NUMEROCASA,
    A.APELLIDOJEFE,
    A.BARRIO,
    A.PROVINCIA,
    A.MUNICIPIO,
    A.SECCION,
    A.PARAJE,
    A.FECHA,
    A.FECHAVISITA,
    A.TENDENCIA,
    A.PAREDES,
    A.TECHO,
    A.PISO,
    A.SERVICIOSSANITARIO,
    A.AGUAINSTALACION,
    A.ABASTECIMIENTOAGUA,
    A.BASURA,
    A.ELECTRICIDAD,
    A.DORMITORIOS,
    A.COMBUSTIBLECOCINA,
    A.ANIMALESDOMESTICOS,
    A.ESPECIFIQUEANIMALES,
    A.VECTORESCRIADEROS,
    A.ESPECIFIQUECRIADEROS,
    A.PUNTUACION,
    A.CUALIFICACION,
    A.CODIGOREGION,
    A.CODIGOAREA,
    A.CODIGOZONA,
    A.CODIGOUNAP,
    A.TELEFONO,
    A.SUBBARRIO,
    B.nombreregion,
    C.nombrearea,
    D.nombrezona,
    I.nombreunap,
    E.nombreprovincia,
    F.nombremunicipio,
    G.nombreseccion,
    H.nombreparaje
FROM
    FICHAFAMILIAR A
LEFT JOIN regionsalud B ON A.codigoregion = B.codigoregion
LEFT JOIN areadesalud C ON A.codigoregion = C.codigoregion AND A.codigoarea = C.codigoarea
LEFT JOIN zonasdesalud D ON A.codigoregion = D.codigoregion AND A.codigoarea = D.codigoarea AND A.codigozona = D.codigozona
LEFT JOIN unap I ON A.codigounap = I.codigounap AND A.codigoarea = I.codigoarea AND A.codigozona = I.codigozona AND A.codigoregion = I.codigoregion

LEFT JOIN provincias E ON A.provincia = E.codigoprovincia
LEFT JOIN municipio F ON A.municipio = F.codigomunicipio AND A.provincia = F.codigoprovincia
LEFT JOIN secciones G ON A.seccion = G.codigoseccion AND A.municipio = G.codigomunicipio AND A.provincia = G.codigoprovincia
LEFT JOIN parajes H ON A.paraje = H.codigoparaje AND A.municipio = H.codigomunicipio AND A.provincia = H.codigoprovincia AND A.seccion = H.codigoseccion
ORDER BY NUMEROFICHA

Cada uno de los campos de las relaciones son campos primarios...
Uso Delphi 2007 con FIBplus 6.8, este query es para darle mantenimiento a la tabla FICHAFAMILIAR.

Neftali [Germán.Estévez] 11-11-2008 17:29:56

¿Y qué quieres que comentemos?

xander 11-11-2008 18:48:29

no, pus muy bonito query... miralo... con su select y toda la cosa.. :D

enecumene 11-11-2008 18:53:19

Cita:

Empezado por Neftali (Mensaje 325307)
¿Y qué quieres que comentemos?

Lo mismo pregunto.

Cita:

Empezado por xander (Mensaje 325326)
no, pus muy bonito query... miralo... con su select y toda la cosa.. :D

:D :D :D

roman 11-11-2008 19:06:32

A mi lo que me gusta de este query es que hasta el apodo del jefe obtienes

Cita:

Empezado por El_Raso
Código SQL [-]
SELECT
    A.NUMEROFICHA,
    A.NOMBREJEFE,
    A.APODOJEFE,
    A.CALLE,
    A.NUMEROCASA,
    A.APELLIDOJEFE,
    A.BARRIO,
    A.PROVINCIA,
    A.MUNICIPIO,

// Saludos

Caral 11-11-2008 19:24:50

Hola
Casi entiendo que estan todos los campos, si no es así, son un montón.
No seria mas facil un SELECT * ???
Saludos

Delphius 11-11-2008 20:01:56

Cita:

Empezado por Caral (Mensaje 325335)
Hola
Casi entiendo que estan todos los campos, si no es así, son un montón.
No seria mas facil un SELECT * ???
Saludos

A riesgo de equivocarme, creo que no funcionaría. Intervienen muchas tablas, y la verdad es que en estos momentos no recuerdo bien como es que actúa el motor:

O trae todos los campos de todas las tablas, o si informa de un error al no saber sobre que campos y de que tablas extraer los campos.

Si es diferente si se empleara algo como:

Código SQL [-]
A.*
;):D


En lo personal prefiero dejar explícito que campos extraer. El empleo del asterisco en tablas con muchos campos puede hacer un poco más "lento" la consulta. Puesto que debe recorrer la/s tabla/s horizontalmente extrayendo los campos correspondiente.

Saludos,

jhonny 11-11-2008 20:30:58

Usar select *, que relentiza al menos un poco las consultas, ya que según tengo entendido el motor tiene que ir a las tablas del sistema para "averiguar" cuales son los campos de dicha tabla, mientras que si le pasas el nombre tu mismo, él ya no tiene que hacer eso y es un paso (que aunque lo hace rapido) se ahorra.

Bueno, al menos eso es lo que yo tengo entendido...

roman 11-11-2008 20:41:27

Bueno, pero el tiempo en que el motor consulta los campos seguramente es menor que el tiempo que yo tardo en escribirlos en la consulta, con lo cual compensa :D

// Saludos

Delphius 11-11-2008 20:42:36

Cita:

Empezado por jhonny (Mensaje 325356)
Usar select *, que relentiza al menos un poco las consultas, ya que según tengo entendido el motor tiene que ir a las tablas del sistema para "averiguar" cuales son los campos de dicha tabla, mientras que si le pasas el nombre tu mismo, él ya no tiene que hacer eso y es un paso (que aunque lo hace rapido) se ahorra.

Bueno, al menos eso es lo que yo tengo entendido...

Efectivamente, primero debe ejecutar una consulta a las tablas del sistema para saber los campos.

Luego, una vez extraído los campos, puede ejecutar la consulta en cuestión.

Saludos,

Caral 11-11-2008 20:55:56

Hola
Sabia que crearía polémica:D
Lo que dice El_Raso:
Cita:

Uso Delphi 2007 con FIBplus 6.8, este query es para darle mantenimiento a la tabla FICHAFAMILIAR.
Perdón pero que mantenimiento se pretende de un select ?.
Lo que creo es que lo que quiere es visualizar el contenido de ciertos campos de ciertas tablas, pero como no indica los campos que tiene cada tabla puedo pensar que son todos (la lista es grande) y después actualizar la tabla FichaFamiliar.
Por otra parte coincido con vosotros en lo que habéis dicho.:)
Saludos

jhonny 11-11-2008 21:05:17

Cita:

Empezado por roman (Mensaje 325360)
Bueno, pero el tiempo en que el motor consulta los campos seguramente es menor que el tiempo que yo tardo en escribirlos en la consulta, con lo cual compensa
// Saludos

Creeme que me haz hecho sentir identificado :D:D:D, cuando el lado perezoso de mi cerebro piensa esas cosas, el otro dice:

- "A ver Jhonny, sumemos el tiempo que te gastas escribiendo los nombres de los campos y comparemos contra las veces que se ejecutará esa consulta".

- El perezoso no se queda atras y dice, listo pues, pero entonces abramos el IBExpert, ejecutemos select * from tabla y vamos a la pestañita que esta abajo de los resultados que se llama "Query Columns" (Ahí aparecen todos los nombres de las columnas separadas por comas), seleccione todo, copie y pegue :D.

Caramba!!!, que cantidad de cosas que uno tiene que pensar :D:D:D

P.D: Vieron que si habia bastante para comentar en este hilo?

Delphius 11-11-2008 21:26:12

Bueno, y volviendo al hilo... ¿que debemos comentar?:confused:
Yo no demasiado lio, si admito que llama la atención la cantidad de join que hace. Al menos en teoría son operaciones "lentas" Pero bueno... no vamos a volver a analizar si es lento o no, .... ¿o si?:D

La cuestión es que con analizar una instrucción SQL no basta como para decir, que está bien o mal. Necesitamos más material con el cual podamas analizar y debatir.
El_Raso, te agradecería que nos comentaras algo más al respecto para que podamos darte sugerencias, críticas, alternativas, etc.

Saludos,

Lepe 11-11-2008 22:01:24

Chicos, sólo hace 5 horas que ha puesto la duda y ¿ya exigen que dé una respuesta? déjenlo respirar ¿no? También tiene vida fuera de los foros.


OFFTOPIC: Tenía que decirlo o reventaba :D :D :D :D.

hecospina 11-11-2008 22:31:24

Pues Lepe tiene toda la razon, no debemos acosarlo con mas preguntas, algun dia......... regresara para mirar nuestras respuestas

Pero analizando hay cositas que le sobran por ejemplo


Código SQL [-]
......
LEFT JOIN areadesalud C ON A.codigoregion = C.codigoregion AND A.codigoarea = C.codigoarea
LEFT JOIN zonasdesalud D ON A.codigoregion = D.codigoregion AND A.codigoarea = D.codigoarea AND A.codigozona = D.codigozona
LEFT JOIN unap I ON A.codigounap = I.codigounap AND A.codigoarea = I.codigoarea AND A.codigozona = I.codigozona AND A.codigoregion = I.codigoregion
......
LEFT JOIN municipio F ON A.municipio = F.codigomunicipio AND A.provincia = F.codigoprovincia
LEFT JOIN secciones G ON A.seccion = G.codigoseccion AND A.municipio = G.codigomunicipio AND A.provincia = G.codigoprovincia
LEFT JOIN parajes H ON A.paraje = H.codigoparaje AND A.municipio = H.codigomunicipio AND A.provincia = H.codigoprovincia AND A.seccion = H.codigoseccion
......





para mi solo quedaria asi


Código SQL [-]
....
LEFT JOIN areadesalud C ON A.codigoregion = C.codigoregion
LEFT JOIN zonasdesalud D ON A.codigoregion = D.codigoregion
LEFT JOIN unap I ON A.codigounap = I.codigounap
......
LEFT JOIN municipio F ON A.municipio = F.codigomunicipio
LEFT JOIN secciones G ON A.seccion = G.codigoseccion
LEFT JOIN parajes H ON A.paraje = H.codigoparaje
....





!Que impaciencia, estamos muy urgidos que él lea nuestras respuestas¡ :D

Neftali [Germán.Estévez] 12-11-2008 11:08:20

Cita:

Empezado por Neftali (Mensaje 325307)
¿Y qué quieres que comentemos?

... wainting for response ...

enecumene 12-11-2008 13:35:17

Cita:

Empezado por Neftali (Mensaje 325472)
... wainting for response ...

¿Wainting = Waiting? :confused: :confused: :confused:

Neftali [Germán.Estévez] 12-11-2008 14:25:24

Cita:

Empezado por enecumene (Mensaje 325488)
¿Wainting = Waiting? :confused: :confused: :confused:

Pues sigo ...waiting... a que este señor nos consteste, ¿Qué quiere que comentemos?
Porque yo sigo sin tenerlo claro...

El_Raso 12-11-2008 19:38:34

Gracias a todos por los comentarios.... en realidad lo que ando buscando es la rapidez en la consulta... ahora bien... porque tantas relaciones? porque los datos lo presento en un cxDBgrid de la Quantum que uso (6.38) y necesito mostrar no los codigo (de la provincia, municipio, etc) si no la descripcion.

Como la respuesta de hescopina es que esperaba algunas de ustedes... pero me gustaron muy jocosas...

Y en conclusion lo que quiero es que me comenten de que forma puedo optimizar el query ya que voy a manejar millones de registros en un grid como lo comente mas arriba.

Y gracias a todos por sus comentarios....sigan por favor....

El_Raso 12-11-2008 19:40:32

Funcionaria igual el query hescopina?, con la forma que propones?

hecospina 12-11-2008 20:09:43

Pues como lo plantee solo tu puedes probarlo, el caso es que lo que queria mostrar era que no es necesario enlazar las tablas en un misma linea varias veces por ejemplo
Código SQL [-]
LEFT JOIN areadesalud C ON A.codigoregion = C.codigoregion AND A.codigoarea = C.codigoarea

yo pienso que quedaria mejor asi
Código SQL [-]
LEFT JOIN areadesalud C ON A.codigoarea = C.codigoarea

Solo debes enlazar la tabla A con la tabla que contenga el nombre de la otra tabla, las demas relaciones sobran.

Me imagino que en la tabla "areadesalud C" esta en nombre del area?

Otra cosa si puedes garantizar que las llaves foraneas nunca estaran nulas podrias hacerlo con inner join y no con left que es mas lento, prueba y notaras la diferencia

de todos modos sin saber el contenido de las tablas es muy dificil plantear algo mejor que esto

:)

Delphius 12-11-2008 20:15:01

Al igual que hecospina opino que hay algunas relaciones que están de más. Pero para estar seguro, sería útil que nos indicades y nos describas como es la relación entre las tablas, tal vez se pueda conseguir algo más simple.

Por el otro lado, mencionas millones de registros. ¿Al usuario?:eek: Sabiendo que son millones de registros sería bueno poder reducir esa consulta... como he dicho antes, si conocieramos más o menos como es el DER podríamos ver como hacer esto de mejor manera.

Saludos,

eduarcol 12-11-2008 20:55:59

y porque, si lo que quieres es el nombre de la provincia y tienes su codigo, deberias utilizar campos lookup en el dataset...

PD. aunque no se como trabajarian con millones de registros, es posible que puedas filtrar esa informacion

Lepe 12-11-2008 23:31:16

Mientras no intente mostrar ese millon de registros en el grid no hay problema, para algo está el optimizador de Firebird y el plan de ejecución de los SQL .

En principio, si pone una restricción where muy fuerte (que solo devuelva 100 registros, por ejemplo), no creo se demore mucho.

Saludos

El_Raso 13-11-2008 00:08:27

Gracias Nuevamente por contestar...
hescopina y delphius lo que pasa es lo siguiente.... tengo:

CodigoRegion = 1 CodigoRegion=2
CodigoArea=1 CodigoArea=1
CodigoZona=1 CodigoZona=1
Osea que el codigo de area podria repetirse...
Y los tres campos me forman la llave primaria... es por eso que uso el AND. ahora todavia tengo
tiempo de asignar los codigos de Area, Zona y demas de forma automatica... eso me optimizaria
el query... que es lo quen en realidad quiero su opinion de eso....

y gracias a ti lepe tambien.. pero una pregunta...
Cual seria mas rapido en un grid, un campo lookup o una relacion directamente en el query?
Los grid de la Quantum (cxDBgrid) agrupan y filtran por cada columda de manera automatica y son muy rapidos...

Otra cosa lepe que es el optimizador de Firebird y el plan de ejecución de los SQL?

Gracias nuevamente

Lepe 13-11-2008 00:37:54

Para añadir la integridad referencial, puedes basarte en esto si googleas un rato, seguro que encuentras un manual sql decente.

Código SQL [-]
CREATE TABLE EQUIPO(
CLAVEEQUIPO INTEGER NOT NULL,
CLAVEPERSONA INTEGER NOT NULL,
NOMBREEQUIPO VARCHAR(100),
PRECIO FLOAT,
FECHA_ASIGNACION DATE,
PRIMARY KEY(CLAVEEQUIPO),
FOREIGN KEY(CLAVEPERSONA) REFERENCES PERSONAS(CLAVEPERSONA) ON DELETE CASCADE)

Yo he añadido las 3 últimas palabras, así consigues que al borrar una persona en la tabla PERSONAS, se borre todos los registros asociados en la tabla EQUIPOS.

Yo, para evitar claves compuestas, haría un diseño distinto, pero podría ser peor que el tuyo :eek:, prefiero que alguien que haya realizado un diseño similar, pueda orientarte.

Personalmente no me gustan los campos LookUp, prefiero hacerlo por sql. He usado pocas veces esos tipos de campos y las veces que lo hice, acabé quitándolos.

El plan de ejecución, es la forma interna en que Firebird une las tablas de tu sql, para llegar a formar el resultado total (la unión de todas). El optimizador es el encargado de:
- mirar los campos que has seleccionado
- ver los índices de cada tabla y elegir el más adecuado para tu sql actual.
- unir las tablas en un orden determinado para que el proceso sea el más rápido.
- chequear la restricción where de tu sql para aplicarla cuanto antes y así, hacer la union de las tablas con los mínimos registros posibles (obviamente cuantos más registros, más tarda la consulta en generarse).

FlameRobin es parecido a IB Expert y te muestra en un esquema ese plan de ejecución. En consultas muy concretas, es necesario modificar el plan manualmente para optimizarla al máximo. También es bueno echarle una visual no más para aprender ;).

Saludos.

Neftali [Germán.Estévez] 13-11-2008 11:09:08

Hombre!, qué alegrías; Al fin apareciste... ;)

Cita:

Empezado por El_Raso (Mensaje 325582)
...ando buscando es la rapidez en la consulta...

porque los datos lo presento en un cxDBgrid de la Quantum

quiero es que me comenten de que forma puedo optimizar el query ya que voy a manejar millones de registros en un grid

En general, para obtener rapiudez, yo te recomendaría (algunas cosas ya las han comentado):
* Utilizar las menos JOIN's posibles en la consulta (las necesaria)
* No mostrar más campos de los necesarios.
* INNER JOIN infinitamente más rápido que el resto (LEFT, RIGHT,...) siempre que sean posibles.
* Indices únicos (PK) en los campos que utilices para las JOIN. Si utilizas claves, simpre numéricas y simples (no varios campos).
* En el caso de SQL server (por ejemplo) se pueden definir indices "clústered" que aumentan la velocidad (1 por tabla). Si hay algo similar utilízalo.
* Revisa el plan de ejecución (si tienes posibilidad) para ver los cuellos de botella de tu consula. A partir del plan concreto, se puede "afinar" un poco más...

En cuanto al grid de las Quantum, recorder que es muy bonito, pero nos es de los más rápidos en cargar. Recuerda que los Grid de las Quantum tienen dos modos de trabajo, uno que cargan datos por bloques y otro que carga todos los datos. Piensa bin el que vas a usar, contando que el que carga por bloques desactiva las agrupaciones, ordenaciones y filtros (que tan bonitos son en el Grid de las Quantum).

Por ultimo olvídate de esto: "...voy a manejar millones de registros en un grid.".
Un Grid está pensado para mostrar un conjunto de registros que un usuario pueda manejar. Mostrar más de 2000 registros enun DBGrid es inútil para un usuario e ineficiente. No quiero ni pensar (dudo que puedas) mostrar millones. Utiliza filtros, TOP,....

gmontes 13-11-2008 19:13:47

yo la duda que tengo es, que se guarda en este campo??

:eek:
Cita:

I.nombreunap,

El_Raso 13-11-2008 22:35:59

Gracias neftali por tu comentario.... en verdad los de millones de registro es para hacer consulta... creo que nunca lo llegaria a mostrar en un grid... Gracias nuevamente..
Una cosa mas neftali... mirando tu el query es posible usar inner en vez de left... seria igual el resultado?...
Todas las tablas que utilizo en las relaciones solo tienen 2 campos (y nunca null) y uso las relaciones solo para desplegar la descripcion del registro ya que solo gurdo el codigo en la tabla principal del query.




gmontes... ese campo es la descripcion (o el nombre) de un campo de una tabla llamada UNAP... en la tabla ficha de familia solo guardo el codigo un smallint y con la relacion (con el join) agrego al query el campo Nombre o la Descripcion del registro que me interesa de esa tabla...

Neftali [Germán.Estévez] 14-11-2008 10:44:54

Cita:

Empezado por El_Raso (Mensaje 325936)
...mirando tu el query es posible usar inner en vez de left... seria igual el resultado?...

Si no tienes valores nulos, LEFT o RIGHT debería devolver el mismo resultado que INNER. Si es así, utiliza INNER.

lbuelvas 14-11-2008 18:40:31

Cita:

Empezado por Neftali (Mensaje 325745)
* INNER JOIN infinitamente más rápido que el resto (LEFT, RIGHT,...) siempre que sean posibles.

Cuando la llave foranea es mandatoria, es decir, que tiene obligatoriamente un valor que coincide con un valor en la otra tabla, puedes utilizar inner join o left outer join (algunos manejan left join simplemente).

Deben hacerse pruebas con una opcion o con la otra, no recomiendo el rigth join en lo personal me ralentiza casi siempre las consultas.

Casi siempre en las bases de datos que he diseñado obtengo ventajas en velocidad con el left join versus el inner join.

Lepe 14-11-2008 19:44:02

Cita:

Empezado por lbuelvas (Mensaje 326162)
Casi siempre en las bases de datos que he diseñado obtengo ventajas en velocidad con el left join versus el inner join.

Tú lo has dicho, del diseño viene todo ;), has hecho bien con incluir el "casi siempre" y no generalizar.

Saludos

Neftali [Germán.Estévez] 18-11-2008 10:53:08

Cita:

Empezado por lbuelvas (Mensaje 326162)
Casi siempre en las bases de datos que he diseñado obtengo ventajas en velocidad con el left join versus el inner join.

:eek::eek::eek::eek:
La verdad que es la primera vez que lo oigo y todavía no acabo de entender muy bien cómo puede ser.
¿Hablamos de Bases de datos de escritorio?
Me gustaría ver los plabnes de ejecución de la misma consulta con LEFT JOIN y con INNER JOIN.

Un saludo.

Patricio 18-11-2008 12:53:44

coincido en cuanto al inner y left
 
en mi poca experiencia hay una gran diferencia a favor del inner que el left join, ahora para ir achicando y que no quede una consulta tan grande no podrias hacer algunas views para ir tomando algunos datos por separado y te quedaria una consulta mas pequeña y facil de relacionar, creo no?


La franja horaria es GMT +2. Ahora son las 21:20:17.

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