Foros del Web » Programación para mayores de 30 ;) » Bases de Datos General » PostgreSQL »

uso de left join y sum

Estas en el tema de uso de left join y sum en el foro de PostgreSQL en Foros del Web. Amigos, tengo una duda... Tiro la siguiente consulta: Código: # SELECT est_002, sum(agri04_005) FROM agri04 LEFT OUTER JOIN public.estado USING (reg_001, est_001) WHERE agri04_001 = ...
  #1 (permalink)  
Antiguo 26/07/2010, 11:00
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
uso de left join y sum

Amigos, tengo una duda...

Tiro la siguiente consulta:
Código:
# SELECT est_002, sum(agri04_005)
FROM agri04 LEFT OUTER JOIN public.estado USING (reg_001, est_001)
WHERE agri04_001 = '2006'
GROUP BY est_002
ORDER BY est_002;
Que me devuelve:
Código:
 est_002  |   sum    
----------+----------
 Mérida   | 29555.05
 Táchira  | 43560.38
 Trujillo | 18247.05
(3 filas)
Resulta, que cuando tiro la misma consulta para el año 2005, me devuelve un sólo registro...

¿al utilizar LEFT JOIN no debería traerme los 3 estados, aunque no tengan datos? o el SUM es tan especial que requiere un tratamiento especial?
__________________
Gracias de todas todas
-----
Linux!
  #2 (permalink)  
Antiguo 26/07/2010, 12:21
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: uso de left join y sum

cacr

Habría que mirar que valores tienen las tablas y a que tabla pertenecen los campos que llamas en el select.

Cabe aclarar que cuando tienes valores nulos y haces un sum, solo sumará aquellos que tienen valores y omitirá los nulos.

Para evitar esto podrías probar algo así:
Código SQL:
Ver original
  1. SELECT est_002, SUM(COALESCE(agri04_005,0))
  2. FROM agri04 LEFT OUTER JOIN public.estado USING (reg_001, est_001)
  3. WHERE agri04_001 = '2006'
  4. GROUP BY est_002
  5. ORDER BY est_002;

saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #3 (permalink)  
Antiguo 27/07/2010, 06:56
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

Eu
Cita:
Iniciado por huesos52 Ver Mensaje
cacr

Habría que mirar que valores tienen las tablas y a que tabla pertenecen los campos que llamas en el select.
La estructura es:
Código:
# \d+ estado
                         Tabla «estado»
 Columna |         Tipo          | Modificadores |     Descripción     
---------+-----------------------+---------------+---------------------
 reg_001 | character varying(2)  | not null      | Código de la Región
 est_001 | character varying(2)  | not null      | Código del Estado
 est_002 | character varying(35) | not null      | Nombre del Estado

=# \d+ agri04
                                                     Tabla «agricola.agri04»
  Columna   |         Tipo         |                    Modificadores                    |              Descripción               
------------+----------------------+-----------------------------------------------------+----------------------------------------
 id         | integer              | not null default nextval('agri04_id_seq'::regclass) | 
 reg_001    | character varying(2) | not null                                            | 
 est_001    | character varying(2) | not null                                            | 
 agri04_001 | character varying(4) | not null                                            | Año de levantamiento de la información
 agri03_001 | integer              |                                                     | Rubro
 agri04_003 | numeric(10,2)        |                                                     | Superficie Sembrada en Fundación
 agri04_004 | numeric(10,2)        |                                                     | Superficie Sembrada en Renovación
 agri04_005 | numeric(10,2)        |                                                     | Total superficie sembrada
algunos datos:
Código:
# SELECT * FROMestado;
 reg_001 | est_001 | est_002  
---------+---------+----------
 06      | 14      | Mérida
 06      | 20      | Táchira
 06      | 21      | Trujillo
(3 filas)

# SELECT id, reg_001, est_001, agri04_001, agri04_003, agri04_004, agri04_005 FROM agri04 LIMIT 5;
  id  | reg_001 | est_001 | agri04_001 | agri04_003 | agri04_004 | agri04_005 
------+---------+---------+------------+------------+------------+------------
  334 | 06      | 14      | 2005       |            |            |      62.00
  583 | 06      | 14      | 2004       |            |            |      60.00
 5500 | 06      | 20      | 2007       |            |            |     116.55
 5498 | 06      | 20      | 2007       |            |            |     116.55
 5499 | 06      | 20      | 2007       |            |            |   11655.00
(5 filas)
Cita:
Iniciado por huesos52 Ver Mensaje
Cabe aclarar que cuando tienes valores nulos y haces un sum, solo sumará aquellos que tienen valores y omitirá los nulos.
Está clarísimo, sí no tiene nada que sumar, pues no suma nada.

Ahora, normlamente, con selects que no involucran campos con funciones de agregación, el join me devolvería los 3 estados aún y cuando sobre éstos no existan datos. Tal es el ejemplo de la documentación [0]
Código:
To put this together, assume we have tables t1:

 num | name
-----+------
   1 | a
   2 | b
   3 | c
and t2:

 num | value
-----+-------
   1 | xxx
   3 | yyy
   5 | zzz
en la que, por ejemplo:
Código:
SELECT * FROM t1 LEFT JOIN t2 USING (num);
 num | name | value
-----+------+-------
   1 | a    | xxx
   2 | b    |
   3 | c    | yyy
(3 rows
Por lo que empiezo a asumir, que con funciones de agregación, la cosa puede ser diferente...

Cita:
Iniciado por huesos52 Ver Mensaje
Para evitar esto podrías probar algo así:
Código SQL:
Ver original
  1. SELECT est_002, SUM(COALESCE(agri04_005,0))
  2. FROM agri04 LEFT OUTER JOIN public.estado USING (reg_001, est_001)
  3. WHERE agri04_001 = '2006'
  4. GROUP BY est_002
  5. ORDER BY est_002;

saludos
nop, no funciona...

[0]http://www.postgresql.org/docs/current/static/queries-table-expressions.html
__________________
Gracias de todas todas
-----
Linux!
  #4 (permalink)  
Antiguo 27/07/2010, 08:07
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

Leyendo y relyendo la documentación:
Cita:
LEFT OUTER JOIN
First, an inner join is performed. Then, for each row in T1 that does not satisfy the join condition with any row in T2, a joined row is added with null values in columns of T2. Thus, the joined table always has at least one row for each row in T1.

RIGHT OUTER JOIN
First, an inner join is performed. Then, for each row in T2 that does not satisfy the join condition with any row in T1, a joined row is added with null values in columns of T1. This is the converse of a left join: the result table will always have a row for each row in T2.
me doy cuenta que, para mi caso, no es left sino right, y sin embargo, no obtengo los resultados que busco

Por si hay sospechas, hice el ejemplo de la doc en una BD pruebas y esa sí furula...
__________________
Gracias de todas todas
-----
Linux!
  #5 (permalink)  
Antiguo 27/07/2010, 09:02
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: uso de left join y sum

cacr...
Me dices que si la haces para 2006 te regresa 3 registros (Lo esperado)
Si lo haces con 2005 te regresa un solo registro.

Debes tener en cuenta que la consulta aplica el left o right join de acuerdo a la inf. que le pidas a las tablas, no a toda la información.

Entonces... si te devuelve 1 solo registro, sospecharía que es el registro que retorna merida... me equivoco?
Creo que es un problema mas de condiciones que no cumplen simultaneamente el año con la información solicitada y que está siendo escondida por el where.

Si lo que digo es cierto, si ejecutas esto:

Código SQL:
Ver original
  1. SELECT *FROM agri04 WHERE agri04_001 = '2006';
debes encontrar registros que cumplan con reg_001 y est_001 en (06 14) en (06 20) y (06 21)

Mientras que si ejecutas
Código SQL:
Ver original
  1. SELECT *FROM agri04 WHERE agri04_001 = '2005';

solo encontraras registros que coincidan con (06 14)

Nos cuentas como te va.

saludos
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #6 (permalink)  
Antiguo 27/07/2010, 09:44
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

Toda esa teoría es muy acertada huesos52, pero... no choca con la teoría del left(rigth) join? donde dice:
Cita:
...a joined row is added with null values in columns...
?
__________________
Gracias de todas todas
-----
Linux!
  #7 (permalink)  
Antiguo 27/07/2010, 09:48
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: uso de left join y sum

No choca cacr.... Por que en la condición estas filtrando los registros que solo coinciden con esto.
El left o right join opera antes de la condición, pero el where se encarga de eliminar de la lista, todos aquellos registros que no cumplan la condición.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #8 (permalink)  
Antiguo 27/07/2010, 09:58
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

Vale... el where filtra después...
Una luz fuera del topic, y si quiero que me aparezcan ¿cuál debería ser el camino?
__________________
Gracias de todas todas
-----
Linux!
  #9 (permalink)  
Antiguo 27/07/2010, 10:02
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: uso de left join y sum

Dejame masticarlo!!
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #10 (permalink)  
Antiguo 27/07/2010, 10:15
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

Cómo ves esto?

Código:
SELECT t1.estado, t2.campo 
FROM (SELECT est_002 AS estado, reg_001, est_001
	FROM public.estado 
	WHERE reg_001 = '06') AS t1
LEFT JOIN (SELECT sum(agri04_005) AS campo,reg_001, est_001
	FROM agri04 
	WHERE reg_001 = '06' AND agri04_001 = '2005'
	GROUP BY reg_001, est_001) AS t2
ON (t1.reg_001=t2.reg_001 AND t1.est_001=t2.est_001)
Lo lancé y me hizo algo, que se parece a lo que busco
__________________
Gracias de todas todas
-----
Linux!
  #11 (permalink)  
Antiguo 27/07/2010, 10:36
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: uso de left join y sum

Definitivamente la solución son subconsultas.

A mi se me ocurrió algo similar


Código SQL:
Ver original
  1. SELECT
  2. t.estado,
  3. SUM(COALESCE(t.valor,0)) AS suma_definitiva
  4. FROM
  5. (
  6.  SELECT  
  7.     e.est_002 AS estado,
  8.     e.reg_001,
  9.     e.est_001,
  10.     a.agri04_001 AS ano,
  11.     a.agri04_005 AS valor
  12.  FROM estado e
  13.  LEFT JOIN
  14.  agri04 a
  15.  ON
  16.  (e.reg_001,e.est_001)=(a.reg_001,a.est_001)
  17. ) AS t
  18. WHERE t.ano = '2005'
  19. GROUP BY t.estado;
EDITO
o así
Código SQL:
Ver original
  1. SELECT
  2. t.estado,
  3. SUM(COALESCE(t.valor,0)) AS suma_definitiva
  4. FROM
  5. (
  6.  SELECT  
  7.     e.est_002 AS estado,
  8.     e.reg_001,
  9.     e.est_001,
  10.     a.agri04_001 AS ano,
  11.     a.agri04_005 AS valor
  12.  FROM estado e
  13.  LEFT JOIN
  14.  agri04 a
  15.  ON
  16.  (e.reg_001,e.est_001)=(a.reg_001,a.est_001)
  17. ) AS t
  18. GROUP BY t.estado
  19. HAVING t.ano = '2005';

No tengo como probarla.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming

Última edición por huesos52; 27/07/2010 a las 10:46
  #12 (permalink)  
Antiguo 27/07/2010, 10:56
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

Le pasa lo mismo huesos52, el where está después y filtra.

Por el camino de las subconsultas me vuelvo a tirar

De todas todas, mil gracias!
__________________
Gracias de todas todas
-----
Linux!
  #13 (permalink)  
Antiguo 27/07/2010, 11:10
Avatar de huesos52
Colaborador
 
Fecha de Ingreso: febrero-2009
Ubicación: Manizales - Colombia
Mensajes: 5.980
Antigüedad: 15 años, 2 meses
Puntos: 360
Respuesta: uso de left join y sum

y la del having?

En teoría el having si se aplica después del agrupamiento.

Nos cuentas como te va.
__________________
Without data, You are another person with an opinion.
W. Edwads Deming
  #14 (permalink)  
Antiguo 27/07/2010, 11:12
 
Fecha de Ingreso: agosto-2005
Ubicación: Mérida, Venezuela
Mensajes: 732
Antigüedad: 18 años, 8 meses
Puntos: 7
Respuesta: uso de left join y sum

idem

having y where se ejecutan, ciertamente, después
__________________
Gracias de todas todas
-----
Linux!

Etiquetas: join, left, sum
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 21:59.