A vueltas con un query
Y va el tercer hilo (Filtrar resultados en un query y ¿Y por qué no funciona el ORDER BY?) con el mismo problema. He encontrado otra manera de sacar los resultados y esta vez funciona:
Las tablas implicadas en el query son estas:
Puede darse la circunstancia de que no se hayan grabado o calculado todavía los electos (tabla NumElectos) para una determinado proceso y/o circunscripción. He hecho la prueba borrando todas las entradas de esa tabla para un determinado proceso y al ejecutar el query no me devuelve ninguna fila aunque el resto de tablas implicadas sí tengan información. Yo tenía la idea que con el LEFT JOIN se obtenía resultados aunque en esa tabla no hubiera información que se ajustara a las condiciones. Si estoy equivocado os rogaría que me iluminaráis. Gracias. |
En este caso debes agregar la condición a la parte de la UNION entre tablas (ON ...)
De esta forma hace el JOIN y como es de tipo LEFT no importa que no tenga datos... Algo así... pero tendrías que utilizar un LEFT JOIN para RESULTADOS porque filtras por mesas que estén en la circunscripcion.
Yo te recomentadría utilizar JOIN / LEFT JOIN para unir las 4 tablas y no mezclar diferentes formas de hacerlo. |
Transformado a JOINS
|
Cita:
|
Cita:
Si no hay datos en NumElectos no saca nada. Seguiré investigando, pero ya mañana. |
Si haces LEFT JOIN con numelectos, también debes hacer LEFT JOIN con las tablas que se unen a ella.
Si numelectos no tiene registros, C.CIRCUNSCRIPCION será nulo y el JOIN con población no devolverá nada.
Para que no se haga eterno deberás tener índices para los campos con los que haces el JOIN. He visto que tienes PKs, que generan índices para estas tablas, pero que quizás no sean óptimos. Por ejemplo Quizás NUMELECTOS debería cambiar el orden de los campos de la PK a CODPRV,PROCESO,TIPO,[PARTIDO <- , -> CIRCUNSCRIPCION],CARGO para que se utilice mejor en el LEFT JOIN. POBLACION debería tener un índice por CODPRV,CODIGO. MESAS no tiene ningún índice. |
Gracias por la orientación.
|
Cita:
POBLACION tiene como clave primaria precisamente esa. MESAS tiene como clave primaria CODPRV, CODIGO. Además tiene otro índice con CODPRV y MUNICIPIO. |
Cita:
|
Pues no sé lo que pasa. El query funciona pero...
Si ejecuto el query como me ha propuesto duilioisola me da este resultado: No veo de donde sale esa suma de votos que, por otra parte, es el único campo que se calcula mal. Por citar sólo un ejemplo el municipio de Alcázar de San Juan tiene un censo electoral de 23670 personas y los votos emitidos fueron 16192. Sin embargo la suma de votos que hace el query es la que se ve ahí. Sin embargo si ejectuto este query sólo para ese municipio: El resultado es este, que es el correcto No veo por qué se multiplican los datos. He comprobado que si divido las resultados de ambos querys de los partidos que tiene electos en todos los casos sale la misma cifra: 44 |
He estado probando añadiendo y quitando trozos del query original y descubierto que el problema viene con el último LEFT JOIN:
Si se deja, salen mal los datos. |
Cada vez estoy más desanimado con este query, y mira que pintaba bien.
He hecho la prueba con left join resultados y con join resultados y eliminando resultados en la tabla NumElectos para que de un municipio no hubiera esos campos pero sí resultados. Y con las tablas completas sale este resultado: pero si suprimo lo que he comentado sale esto aunque en la tabla resultados siga habiendo datos del municipio en cuestión (en este caso el 175). No lo entiendo: con LEFT JOIN ¿no deberían salir datos para ese valor? No sé que estoy haciendo mal o no entendiendo. En el enlcae https://drive.google.com/file/d/1F3V...ew?usp=sharing hay un fichero TABLAS.RAR que tiene el script para crear y llenar las tablas implicadas en el query. |
Al descargar el fichero te he pedido acceso.
En cuanto pueda descargarlo haré algunas pruebas para ver qué contienen las tablas... |
He estado mirando las tablas...
Primera parte La primera duda es cómo se unen mesa, poblacion y numelectos. He inferido que mesas.codigo, poblacion.municipio y numelectos.circunscripcion es el mismo campo y lo he utilizado para los joins. La segunda duda es qué es proceso? He inferido que se trata de diferentes votaciones y he estado utilizando la número 42. Segunda parte. Lo primero que necesitas antes de hacer las acumulaciones es la tabla con todos los datos necesarios unidos mediante JOIN / LEFT JOIN.
Este SQL devuelve 113511 registros.
Ahora agrego el where para limitar los datos a tratar. En este caso he elegido alguno que devuelve datos y que hemos hablado en este hilo Este SQL devuelve 8 registros.
Final Ya tenemos los datos. Ahora solo tenemos que agruparlos y ordenarlos.
Dos formas de evitar que salgan registros "sin electos".
|
PD.
Después de ejecutar el script, todo iba muy lento. He tenido que recaclular los índices para que todo vaya bien. IbExpert tiene la opción de ir a DataBase-> Recompute celectivity of all Indeces Básicamente recorre los índices de la base de datos y ejecuta SET STATISTICS INDEX [IndexName]:
|
Cita:
|
Cita:
Por otra parte, sobre la velocidad de ejecución he de decirte que para sacar todos los municipios a mi en SQL Manager me ha tardado 62 milisegundos. Únicamente las lecturas de la tabla mesas se hacen sin usar índices; tengo que ver por qué. |
A mi también me va muy rápida la consulta, pero al principio los índices estaban desbalanceados (supongo que por el insert masivo del script) y todos tenínan un valor de 1 (o 0, no recuerdo bien).
Las estadísticas de los índices es una parte importante de lo que mira el planificador de SQL al hacer los JOINS. Esto te devuelve las estadísticas de los índices y deberían tener valores lo más bajo posibles sin ser 0.
Esto es lo que me devuelve ahora, después de ejeructar el "SET STATISTICS [indice]". Código:
RDB$RELATION_NAME RDB$INDEX_NAME RDB$STATISTICS |
Es decir que cuanto más bajo sea ese valor mejor está el índice. No lo sabía; todos los días se aprende algo.
Otra cosa: Si ejecuto el query para que me saque todos los municipios, cambiando la línea por me ocurre una cosa que, al menos a mi, me llama la atención. Table Operations: +----------------- Table Name | Index | Non-Index | reads | reads +--------------------------+-----------+ MESAS| 0 | 1.476 | NUMELECTOS| 4.534 | 0 | PARTIDOS| 5.786 | 0 | POBLACION| 1.476 | 0 | PROVINCIA| 5.786 | 0 | RESULTADOS| 5.786 | 0 | La tabla mesas tiene tres índices: la clave primaria (CodPrv + Codigo) y dos índices: uno por CodPrv y Municipio y el otro por todos los datos identificativos de la mesa. Y dado que las búsquedas en las que interviene la tabla Mesas se hacen por alguno de los campos indexados, prinicipalmente municipio y código de mesa), ¿por qué no se usan los índices para esas búsquedas? |
El número de los índices indica cuan específico es. Entiéndase cuan único es cada registro.
Si tienes una tabla ARTICULOS (EMPRESA, ARTICULO) y tienes los valores Código:
1, ART1 un índice por ARTICULO tendra estadística = 0,25, indicando que "se repite poco" (en este ejemplo nada) en todos los registros. Por lo tanto, si el planificador de JOINs tiene la opción de usar uno de estos dos índices, preferirá el de artículo. Nota: Un índice por EMPRESA+ARTICULO también tendra estadística = 0,25, indicando que "se repite poco" (en este ejemplo nada) en todos los registros. Creo que estás haciendo el SQL de forma incorrecta. Si no quieres filtrar por municipio, debes eliminar esa línea del WHERE.
Suposición 1 - Agregas lo que mencionas al WHERE. Si haces lo que que mencionas, estarás diciendo que muestre los registros donde el municipio de la mesa sea el municipio de la poblacion. Esto ya está garantizado por los JOINs join mesas m on m.codprv = r.codprv and m.codigo = r.mesa join poblacion po on p.codprv = po.codprv and m.municipio = po.codigo Solo le estarás complicando la vida al planificador.
Suposición 2 - Quitas "m.municipio = po.codigo" del JOIN . Si haces esto, estás cambiando los datos sobre los que haces los cálculos. En ese caso, si tenemos en cuenta solo las tablas MESAS y POBLACION sería
En este caso cada mesa se uniría con todas las poblaciones y tendrías muchísimos registros más. Prueba estos SQL:
|
La franja horaria es GMT +2. Ahora son las 01:52: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