¿Alguna forma de evitar varios FULL OUTER JOIN?

25/02/2004 - 10:23 por Eje | Informe spam
Sigo con el procedimiento aquel que conseguí rebajar de 8 horas a 20 minutos
con vuestra ayuda. Ahora me han cambiado criterios de cálculo y tengo un
nuevo problema.
Para los que no lo recuerden, el procedimiento hace cálculos en 5 tablas, en
función de un periodo dado. Antiguamente se extraían de 2 de esas 5 tablas,
las claves de los registros que había que calcular en las otras 3. Bueno,
pues ahora resulta que no es así, y hay que calcular en las 5 tablas
independientemente, para todas aquellos registros que tengan movimientos en
el periodo de tiempo a calcular.
La cuestión es que algunos registros pueden tener movimientos en unas tablas
sí y en otras no, con lo cual lo que hago es insertar los resultados de cada
una de las 5 tablas en una tabla temporal. Cada tabla temporal tiene 5
campos que forman la clave del registro, y luego entre 2 y 4 campos de
resultados de los cálculos.
El problema viene al tener que reunir todos esos datos para insertarlos en
la tabla real; ya que como puede darse el caso de estar en unas tablas sí y
en otras no, tengo que hacer un FULL OUTER JOIN de las 5 tablas temporales
(por los 5 campos clave).
El proceso ha pasado de 12 minutos a 31, y me pregunto si se os ocurre
alguna alternativa para evitar ese insert con los 4 FULL OUTER JOIN, porque
a mí no se me ocurre ninguna otra.

Un saludo

Preguntas similare

Leer las respuestas

#1 Maximiliano D. A.
25/02/2004 - 13:37 | Informe spam
Hola, lamentablemente sin la estructura y el Query se me hace imposible
poder ayudarte mejor, pero estoy casi seguro que el uso de la tabla temporal
no lo necesitarias.

Si quieres pasame como estas haciendo las cosas y las estructuras bien
detalladas dentro de lo posible y vemos como armarte el Query de forma mas
optima.

Bye


Salu2
Maxi
Buenos Aires Argentina
Desarrollador Microsoft 3 Estrellas .NET
[Maxi_accotto[arroba]speedy[punto]com[punto]ar
MSN:


"Eje" escribió en el mensaje
news:c1hpf2$1hubkc$
Sigo con el procedimiento aquel que conseguí rebajar de 8 horas a 20


minutos
con vuestra ayuda. Ahora me han cambiado criterios de cálculo y tengo un
nuevo problema.
Para los que no lo recuerden, el procedimiento hace cálculos en 5 tablas,


en
función de un periodo dado. Antiguamente se extraían de 2 de esas 5


tablas,
las claves de los registros que había que calcular en las otras 3. Bueno,
pues ahora resulta que no es así, y hay que calcular en las 5 tablas
independientemente, para todas aquellos registros que tengan movimientos


en
el periodo de tiempo a calcular.
La cuestión es que algunos registros pueden tener movimientos en unas


tablas
sí y en otras no, con lo cual lo que hago es insertar los resultados de


cada
una de las 5 tablas en una tabla temporal. Cada tabla temporal tiene 5
campos que forman la clave del registro, y luego entre 2 y 4 campos de
resultados de los cálculos.
El problema viene al tener que reunir todos esos datos para insertarlos en
la tabla real; ya que como puede darse el caso de estar en unas tablas sí


y
en otras no, tengo que hacer un FULL OUTER JOIN de las 5 tablas temporales
(por los 5 campos clave).
El proceso ha pasado de 12 minutos a 31, y me pregunto si se os ocurre
alguna alternativa para evitar ese insert con los 4 FULL OUTER JOIN,


porque
a mí no se me ocurre ninguna otra.

Un saludo







Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.593 / Virus Database: 376 - Release Date: 21/02/2004
Respuesta Responder a este mensaje
#2 Eje
25/02/2004 - 15:09 | Informe spam
Maximiliano D. A.
Hola, lamentablemente sin la estructura y el Query se me hace imposible
poder ayudarte mejor, pero estoy casi seguro que el uso de la tabla


temporal
no lo necesitarias.

Si quieres pasame como estas haciendo las cosas y las estructuras bien
detalladas dentro de lo posible y vemos como armarte el Query de forma mas
optima.



A ver, detallo un poco cómo están las cosas:
5 tablas de datos, todas con la siguiente estructura:
- 1 campo que indica cuando se produjo el movimiento económico.
- 5 campos que identifican quien generó el movimiento.
- varios campos económicos sobre los que se va a realizar el cálculo.

Tienen que quedar ubicados en una tabla con esta estructura:
- los 5 campos que identifican a quien corresponde la información.
- una serie de campos económicos que contienen el total de movimientos
generados por esa persona por cada uno de esos conceptos.

El calculo es sencillo, ya que simplemente se trata de calcular el total de
movimientos económicos realizados por cada persona en el periodo de tiempo,
así que únicamente se hace un INSERT SELECT en cada tabla temporal, que
contiene la suma de los datos económicos de cada tabla, usando SUM y GROUP
BY, muy fácil (así que realmente serían una especie de tablas agregadas
temporales).
Como dije antes se pueden tener movimientos en unas tablas sí y en otras no,
no estando obligado a tener movimientos en ninguna, con lo cual la única
manera de reunir los datos de las tablas temporales es hacer un:

INSERT INTO tablafinal
(lista_de_campos)
SELECT
[COALESCE de cada uno de los 5 campos clave en las 5 tablas], [campos
económicos de las tablas temporales]
FROM tabla_temporal_1 AS T1
FULL OUTER JOIN tabla_temporal_2 AS T2
ON T1.CLAVE1 = T2.CLAVE1 AND
T1.CLAVE2 = T2.CLAVE2 AND
T1.CLAVE3 = T2.CLAVE3 AND
T1.CLAVE4 = T2.CLAVE4 AND
T1.CLAVE5 = T2.CLAVE5
FULL OUTER JOIN tabla_temporal_3 AS T3
ON T3.CLAVE1 = COALESCE(T1.CLAVE1, T2.CLAVE1) AND
T3.CLAVE2 = COALESCE(T1.CLAVE2, T2.CLAVE2) AND
T3.CLAVE3 = COALESCE(T1.CLAVE3, T2.CLAVE3) AND
T3.CLAVE4 = COALESCE(T1.CLAVE4, T2.CLAVE4) AND
T3.CLAVE5 = COALESCE(T1.CLAVE5, T2.CLAVE5)
FULL OUTER JOIN tabla_temporal_4 AS T4
ON T4.CLAVE1 = COALESCE(T1.CLAVE1, T2.CLAVE1, T3.CLAVE1) AND
T4.CLAVE2 = COALESCE(T1.CLAVE2, T2.CLAVE2, T3.CLAVE2) AND
T4.CLAVE3 = COALESCE(T1.CLAVE3, T2.CLAVE3, T3.CLAVE3) AND
T4.CLAVE4 = COALESCE(T1.CLAVE4, T2.CLAVE4, T3.CLAVE4) AND
T4.CLAVE5 = COALESCE(T1.CLAVE5, T2.CLAVE5, T3.CLAVE5)
FULL OUTER JOIN tabla_temporal_5 AS T5
ON T5.CLAVE1 = COALESCE(T1.CLAVE1, T2.CLAVE1, T3.CLAVE1, T4.CLAVE1) AND
T5.CLAVE2 = COALESCE(T1.CLAVE2, T2.CLAVE2, T3.CLAVE2, T4.CLAVE2) AND
T5.CLAVE3 = COALESCE(T1.CLAVE3, T2.CLAVE3, T3.CLAVE3, T4.CLAVE3) AND
T5.CLAVE4 = COALESCE(T1.CLAVE4, T2.CLAVE4, T3.CLAVE4, T4.CLAVE4) AND
T5.CLAVE5 = COALESCE(T1.CLAVE5, T2.CLAVE5, T3.CLAVE5, T4.CLAVE5)

Esto me parece demasiado complejo y no sé si habrá una manera mejor de
reunir todos los datos en la tabla final.

Un saludo
Respuesta Responder a este mensaje
#3 Javier Loria
25/02/2004 - 15:47 | Informe spam
Hola:
No estoy tan seguro que el FULL OUTER JOIN sea el responsable del
problema, estoy casi seguro que son las tablas temporales.
Una sugerencia, y espero haber entendido el problema
a) Crea una Vista que sea la union de todos las tablas tomando en cuenta
solamente los campos que son llaves.
==CREATE VIEW MisLlaves
AS
SELECT [Cada uno de los 5 campos clave]
FROM Tabla1
WHERE [Condicion]
UNION
SELECT [Cada uno de los 5 campos clave]
FROM Tabla2
WHERE [Condicion]
UNION
...
FROM TABLA5
WHERE [Condicion]
== Esta vista como es un UNION debe eliminar todos las filas duplicadas y
tendra una fila para cada juego de llaves. (Es muy probable que esta tabla
deberia existir fisicamente y que represente a una entidad, pero eso es otro
problema).
Entonces el INSERT debe ser:
==INSERT INTO TablaFinal (LISTA CAMPOS)
SELECT [5 Campos de MisLlaves]
, [COALESCE de Campos Economicos]
FROM MisLlaves
LEFT JOIN MiTabla1
ON MisLlaves.Clave1=MiTabla1.Clave1 AND
LEFT JOIN MiTabla2
ON MisLlaves.Clave1=MiTabla2.Clave1 AND

== Prueba primero usando las tablas temporales y luego: Usando el WHERE de
la vista MisLlaves para filtrar los datos; y si haces muchos calculos,
reemplazan la Tabla Temporal por una Vista y haz los calculos en la Vista.
Suerte,

Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.

Eje escribio:
Maximiliano D. A.
Hola, lamentablemente sin la estructura y el Query se me hace
imposible poder ayudarte mejor, pero estoy casi seguro que el uso de
la tabla temporal no lo necesitarias.

Si quieres pasame como estas haciendo las cosas y las estructuras
bien detalladas dentro de lo posible y vemos como armarte el Query
de forma mas optima.



A ver, detallo un poco cómo están las cosas:
5 tablas de datos, todas con la siguiente estructura:
- 1 campo que indica cuando se produjo el movimiento económico.
- 5 campos que identifican quien generó el movimiento.
- varios campos económicos sobre los que se va a realizar el cálculo.

Tienen que quedar ubicados en una tabla con esta estructura:
- los 5 campos que identifican a quien corresponde la información.
- una serie de campos económicos que contienen el total de movimientos
generados por esa persona por cada uno de esos conceptos.

El calculo es sencillo, ya que simplemente se trata de calcular el
total de movimientos económicos realizados por cada persona en el
periodo de tiempo, así que únicamente se hace un INSERT SELECT en
cada tabla temporal, que contiene la suma de los datos económicos de
cada tabla, usando SUM y GROUP BY, muy fácil (así que realmente
serían una especie de tablas agregadas temporales).
Como dije antes se pueden tener movimientos en unas tablas sí y en
otras no, no estando obligado a tener movimientos en ninguna, con lo
cual la única manera de reunir los datos de las tablas temporales es
hacer un:

INSERT INTO tablafinal
(lista_de_campos)
SELECT
[COALESCE de cada uno de los 5 campos clave en las 5 tablas], [campos
económicos de las tablas temporales]
FROM tabla_temporal_1 AS T1
FULL OUTER JOIN tabla_temporal_2 AS T2
ON T1.CLAVE1 = T2.CLAVE1 AND
T1.CLAVE2 = T2.CLAVE2 AND
T1.CLAVE3 = T2.CLAVE3 AND
T1.CLAVE4 = T2.CLAVE4 AND
T1.CLAVE5 = T2.CLAVE5
FULL OUTER JOIN tabla_temporal_3 AS T3
ON T3.CLAVE1 = COALESCE(T1.CLAVE1, T2.CLAVE1) AND
T3.CLAVE2 = COALESCE(T1.CLAVE2, T2.CLAVE2) AND
T3.CLAVE3 = COALESCE(T1.CLAVE3, T2.CLAVE3) AND
T3.CLAVE4 = COALESCE(T1.CLAVE4, T2.CLAVE4) AND
T3.CLAVE5 = COALESCE(T1.CLAVE5, T2.CLAVE5)
FULL OUTER JOIN tabla_temporal_4 AS T4
ON T4.CLAVE1 = COALESCE(T1.CLAVE1, T2.CLAVE1, T3.CLAVE1) AND
T4.CLAVE2 = COALESCE(T1.CLAVE2, T2.CLAVE2, T3.CLAVE2) AND
T4.CLAVE3 = COALESCE(T1.CLAVE3, T2.CLAVE3, T3.CLAVE3) AND
T4.CLAVE4 = COALESCE(T1.CLAVE4, T2.CLAVE4, T3.CLAVE4) AND
T4.CLAVE5 = COALESCE(T1.CLAVE5, T2.CLAVE5, T3.CLAVE5)
FULL OUTER JOIN tabla_temporal_5 AS T5
ON T5.CLAVE1 = COALESCE(T1.CLAVE1, T2.CLAVE1, T3.CLAVE1, T4.CLAVE1)
AND T5.CLAVE2 = COALESCE(T1.CLAVE2, T2.CLAVE2, T3.CLAVE2, T4.CLAVE2)
AND T5.CLAVE3 = COALESCE(T1.CLAVE3, T2.CLAVE3, T3.CLAVE3, T4.CLAVE3)
AND T5.CLAVE4 = COALESCE(T1.CLAVE4, T2.CLAVE4, T3.CLAVE4, T4.CLAVE4)
AND T5.CLAVE5 = COALESCE(T1.CLAVE5, T2.CLAVE5, T3.CLAVE5, T4.CLAVE5)

Esto me parece demasiado complejo y no sé si habrá una manera mejor de
reunir todos los datos en la tabla final.

Un saludo
Respuesta Responder a este mensaje
#4 Eje
27/02/2004 - 16:54 | Informe spam
Bueno, finalmente lo he resuelto usando tus ideas pero sin usar la vista que
me proponías, ya que esta no era posible por cuestiones de diseño interno
(algunas tablas se consultan por intervalos de fechas y otras por diferencia
entre 2 fechas concretas, y todas esas fechas son variables). En lugar de la
vista he creado una nueva tabla temporal que contenía el conjunto de claves,
para poder cambiar los FULL OUTER JOIN por LEFT JOIN.
Con esto el proceso funciona perfectamente, y el tiempo está en unos 17
minutos, lo cual es aceptable y cercano a los 13 minutos que duraba antes de
este último cambio.
Gracias a todos por vuestras ideas y consejos.

Un saludo

"Javier Loria" escribió en el mensaje
news:%23yDNb56%
Hola:
No estoy tan seguro que el FULL OUTER JOIN sea el responsable del
problema, estoy casi seguro que son las tablas temporales.
Una sugerencia, y espero haber entendido el problema
a) Crea una Vista que sea la union de todos las tablas tomando en


cuenta
solamente los campos que son llaves.
==> CREATE VIEW MisLlaves
AS
SELECT [Cada uno de los 5 campos clave]
FROM Tabla1
WHERE [Condicion]
UNION
SELECT [Cada uno de los 5 campos clave]
FROM Tabla2
WHERE [Condicion]
UNION
...
FROM TABLA5
WHERE [Condicion]
==> Esta vista como es un UNION debe eliminar todos las filas duplicadas y
tendra una fila para cada juego de llaves. (Es muy probable que esta tabla
deberia existir fisicamente y que represente a una entidad, pero eso es


otro
problema).
Entonces el INSERT debe ser:
==> INSERT INTO TablaFinal (LISTA CAMPOS)
SELECT [5 Campos de MisLlaves]
, [COALESCE de Campos Economicos]
FROM MisLlaves
LEFT JOIN MiTabla1
ON MisLlaves.Clave1=MiTabla1.Clave1 AND
LEFT JOIN MiTabla2
ON MisLlaves.Clave1=MiTabla2.Clave1 AND

==> Prueba primero usando las tablas temporales y luego: Usando el WHERE


de
la vista MisLlaves para filtrar los datos; y si haces muchos calculos,
reemplazan la Tabla Temporal por una Vista y haz los calculos en la Vista.
Suerte,

Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.
Respuesta Responder a este mensaje
#5 Javier Loria
27/02/2004 - 17:07 | Informe spam
Me alegro que te sirvieran,
Saludos,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.
Eje escribio:
Bueno, finalmente lo he resuelto usando tus ideas pero sin usar la
vista que me proponías, ya que esta no era posible por cuestiones de
diseño interno (algunas tablas se consultan por intervalos de fechas
y otras por diferencia entre 2 fechas concretas, y todas esas fechas
son variables). En lugar de la vista he creado una nueva tabla
temporal que contenía el conjunto de claves, para poder cambiar los
FULL OUTER JOIN por LEFT JOIN.
Con esto el proceso funciona perfectamente, y el tiempo está en unos
17 minutos, lo cual es aceptable y cercano a los 13 minutos que
duraba antes de este último cambio.
Gracias a todos por vuestras ideas y consejos.

Un saludo

"Javier Loria" escribió en el mensaje
news:%23yDNb56%
Hola:
No estoy tan seguro que el FULL OUTER JOIN sea el responsable del
problema, estoy casi seguro que son las tablas temporales.
Una sugerencia, y espero haber entendido el problema
a) Crea una Vista que sea la union de todos las tablas tomando
en cuenta solamente los campos que son llaves.
==>> CREATE VIEW MisLlaves
AS
SELECT [Cada uno de los 5 campos clave]
FROM Tabla1
WHERE [Condicion]
UNION
SELECT [Cada uno de los 5 campos clave]
FROM Tabla2
WHERE [Condicion]
UNION
...
FROM TABLA5
WHERE [Condicion]
==>> Esta vista como es un UNION debe eliminar todos las filas
duplicadas y tendra una fila para cada juego de llaves. (Es muy
probable que esta tabla deberia existir fisicamente y que represente
a una entidad, pero eso es otro problema).
Entonces el INSERT debe ser:
==>> INSERT INTO TablaFinal (LISTA CAMPOS)
SELECT [5 Campos de MisLlaves]
, [COALESCE de Campos Economicos]
FROM MisLlaves
LEFT JOIN MiTabla1
ON MisLlaves.Clave1=MiTabla1.Clave1 AND
LEFT JOIN MiTabla2
ON MisLlaves.Clave1=MiTabla2.Clave1 AND

==>> Prueba primero usando las tablas temporales y luego: Usando el
WHERE de la vista MisLlaves para filtrar los datos; y si haces
muchos calculos, reemplazan la Tabla Temporal por una Vista y haz
los calculos en la Vista. Suerte,

Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida