Ver Mensaje Individual
  #18  
Antiguo 19-01-2009
Bpascal Bpascal is offline
Miembro
 
Registrado: ene 2009
Posts: 14
Reputación: 0
Bpascal Va por buen camino
Hola Amigo,

disculpa la tardanza y disculpa que no fui explicitamente claro con el INNER JOIN, inlcluso no te dije toda la historia, la cual es necesario que la domines de lo contrario no podras hacer querys eficientes.

Por favor lee detalladamente las explicacion a continuacion del JOIN y al final del post te escribo el querry que ocupas.

Primero debes saber que hay dos sabores de JOIN:

INNER JOIN
LEFT OUTER JOIN

si tenemos tabla_A:
Id, englishword
--------------
1 bird
2 house
3 dog
5 cat
6 black

si tenemos tabla_B:
Id, spanishword
--------------
1 pajaro
2 casa
3 perro
5 gato

si hacemos el siguiente select:
Código SQL [-]
SELECT 
 a.id,a.englishword,b.spanishword 
FROM
TABLA_A a
INNER JOIN TABLA_B b ON a.id = b.id

el resultado seria:
Cita:
1 bird pajaro
2 house casa
3 dog perro
5 cat gato
Como vez, el ultimo registro de la tabla_A con id = 6 no aparece en la lista, esto se deve a que INNER JOIN se usa para seleccionar solo los registros que coincidan en el campo relacionado. Como el ID=6 no esta en la tabla_B entonces ese registro no sale. El inner join es mas utilizalo para enlazar tablas de transacciones con su maestro, o tablas detalle con encabezado.

Ahora, si queremos sacar TODOS los registros de la tabla_A con su respectivo dato de la tabla_B pero tambien incluyendo los que no pudieran tener equivalencia en tabla_B entonces harias:

Código SQL [-]
SELECT 
 a.id,a.englishword,b.spanishword 
FROM
TABLA_A a
LEFT OUTER JOIN TABLA_B b ON a.id = b.id


el resultado seria:
Cita:
1 bird pajaro
2 house casa
3 dog perro
5 cat gato
6.black NULL
Los registros que no tengan su correspondiente equivalencia en tabla_B aparece con valor NULL.

Hasta aqui ya te estaras imaginando que lo que necesitas es usar LEFT OUTER JOIN, porque basicamente tu quieres repasar todos los registros de la tabla presupuesto la par con resumenes si (si los hubiera) de la tabla compras.

Sin envargo en estos ejemplo la relacion es de 1 a 1, o almenos de muchos a 1 es decir, por un registro en la tabla A se espera un tan solo registro en la tabla B, pero el asunto se vuleve diferente cuando la relacion es uno a muchos, por ejemplo:

si la tabla B tuviera:
Id, spanishword
--------------
1 pajaro
1 ave
1 plumifero
2 casa
3 perro
5 gato

como vez, el id=1 esta 3 veces

si se aplica el utimo querry el resultado seria:
Cita:

1 bird pajaro
1 bird ave
1 bird plumifero
2 house casa
3 dog perro
5 cat gato
6.black NULL
Entonces tu ves que el dato "bird" de la tabla_A se REPITE 3 veces, una vez por cada registro con el ID=1 encontrado en la tabla B.

Por consiguinete, si tu haces el siguinete querry:

Código SQL [-]
select
p.area , sum(P.monto) , sum(case when estado = 'F' then monto_compr else 0 end),
count(case when estado = 'P' then monto_compr else 0 end)
from presupuesto p 
LEFT OUTER JOIN compras c on c.area = p.area and c.ano = p.ano
and p.mes = c.mes AND P.EMPRESA = C.EMPRESA

where p.mes = '2009'
and p.ano =   '1'
and P.empresa = 'emp'
AND P.oficina = '1'
AND C.OFICINA = 'SANTIAGO'
GROUP BY AREA

Los sum() y los count() de la tabla COMPRAS saldran bien, pero los de la tabla presupuesto saldran mal ya que ahora hay datos duplicados por cada ocurrencia encontrada en compras, de la misma manera como se duplica el dato "Bird" en el ejemplo que te puse tambien aqui el dato p.monto saldra duplicado.

Entonces como se resuleve este tipo de problemas? bueno se resuelve resumiendo la tabla compras UNA TAN SOLA VEZ y enlazando el resultado a la tabla presupuesto usando LEFT OUTER JOIN,

Es decir envez de escribir el nombre de la tabla despues del left outer join se puede perfectamente escribir un SELECT que resume ya la tabla antes de hacer el enlazado, ejemplo:

Cita:
from presupuesto p LEFT OUTER JOIN

(SELECT
area,ano,mes,empresa,oficina,sum(Monto_compr) as T_monto_compr, count(mont_compr) as C_mon_compr
FROM
Compras
group by area,ano,mes,empresa,oficina)

C ON p.area = c.area and p.ano = c.ano and p.mes = c.mes AND P.EMPRESA = C.EMPRESA
Esto nos dara una especie de tabla temporal ya resumida por lo que queramos y poder ser enlazada con otra tabla maestra por ejemplo usando inner o outer join segun sea la necesidad.

Ya terminamos?, no todavia, , c.Tot_compr y c.C_mon_compr ya tienen el total de la compra y la cuenta de la compra lista para enlazarla con una tabla mestra, pero tu todavia necesitas resumir la tabla presupuesto para sumar y contar el valor monto.

La manera de sumarizar la tabla presupuesto e incluir los totales de la tabla compra sin duplicar se puede hacer usando el comando DISTINCT.

creo que este es el querry final:

Cita:

SELECT
p.area , sum(P.monto) , sum(distintc c.tot_compr), sum(distintc c.C_mon_compr)
FROM
presupuesto p
LEFT OUTER JOIN

(SELECT
area,ano,mes,empresa,oficina,sum(Monto_compr) as T_monto_compr, count(mont_compr) as C_mon_compr
FROM
Compras
group by area,ano,mes,empresa,oficina)

C ON p.area = c.area and p.ano = c.ano and p.mes = c.mes AND P.EMPRESA = C.EMPRESA

where p.mes = '2009'
and p.ano = '1'
and P.empresa = 'emp'
AND P.oficina = '1'
AND C.OFICINA = 'SANTIAGO'
GROUP BY AREA
Favor notar que en el select de la tabla compras la estoy resumiendo sin tomar en considerancion el campo estado.


Espero que te funcione o por lo menos te haya dado la suficiente informacion para adaptar tus querrys.

Última edición por Bpascal fecha: 19-01-2009 a las 22:49:00.
Responder Con Cita