Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   SQL (https://www.clubdelphi.com/foros/forumdisplay.php?f=6)
-   -   Agregar SUM a una consulta (https://www.clubdelphi.com/foros/showthread.php?t=48913)

Gabo 08-10-2007 09:59:18

Agregar SUM a una consulta
 
1 Archivos Adjunto(s)
Hola a todos!!

Tengo un problema con una consulta que es para un reporte y necesito sumar algunos campos de ella.

El diagrama de la base de datos lo he adjuntado, y por favor no sean mal pensados, usé Access para dibujar las relaciones y poder mostrárselas, nada más. :D

He llegado hasta esta consulta, como verán hace un resumen de los pagos que debe recibir un trabajador. Por cada demanda de trabajo que el trabajador haya satisfecho, se genera un registro en la tabla DEMANDAPERSONAL. En la consulta que sigue se obtienen todos los pagos que debería recibir un trabajador, pero tengo que modificarla para que me muestre la suma total que debe recibir, es decir, la suma de todos los registros del trabajador y de los campos DEMANDAPERSONAL_EUROS y DEMANDAPERSONAL_EUROSAJUSTE.

He intentado varias formas de insertar la función SUM pero no me sale, ¿alguien tiene alguna idea?

Código SQL [-]
SELECT DEMANDAPERSONAL.PERSONAL_CODIGO, PERSONAL.PERSONAL_CIF, PERSONAL.PERSONAL_NOMBRE,
DEMANDAPERSONAL.DEMANDAPERSONAL_EUROS, DEMANDAPERSONAL.DEMANDAPERSONAL_EUROSAJUSTE FROM DEMANDAPERSONAL left join PERSONAL
ON PERSONAL.PERSONAL_CODIGO=DEMANDAPERSONAL.PERSONAL_CODIGO WHERE DEMANDAPERSONAL.DEMANDA_CODIGO IN
(SELECT DEMANDA.DEMANDA_CODIGO FROM DEMANDA, PAGODEMANDA
WHERE DEMANDA.DEMANDA_CODIGO=PAGODEMANDA.DEMANDA_CODIGO 
AND PAGODEMANDA.PAGODEMANDA_CODIGO=:codPago) ORDER BY DEMANDAPERSONAL.PERSONAL_CODIGO

Creo que me falto decir que uso Interbase 6.

Gabo 08-10-2007 10:25:45

Quería hacer un comentario sobre SUM. Siempre que he leído o consultado manuales de SQL, para aprender el uso de funciones como esta, me encuentro con ejemplos del tipo:

Código SQL [-]
SELECT SUM (CANTIDAD) FROM TABLA

a lo sumo, alguna incluye un ejemplo con agrupación de registros, al estilo:

Código SQL [-]
SELECT CODIGO, SUM (CANTIDAD) FROM TABLA GROUP BY CODIGO

Pero cuando he necesitado el uso de esta función, siempre ha sido en casos de consulta a más de una tabla, al estilo:

Código SQL [-]
SELECT A.CODIGO, A. NOMBRE, B.CANTIDAD FROM A, B WHERE A.CODIGO=B.CODIGO

Y en esos momentos me gustaría insertar un SUM algo así:

Código SQL [-]
SELECT A.CODIGO, A. NOMBRE, SUM(B.CANTIDAD) FROM A, B WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO

Pero siempre me marca error.

Lo que no me termina de quedar claro es si se puede ocupar la función SUM cuando estas consultando más de una tabla. Nunca he visto un ejemplo donde se muestre ese caso.

Si alguno tiene una consulta como la que menciono, le agradecería que la pusiera para poder ver como se hace, ya que así sabría como resolver el problema del mensaje anterior.

pcicom 08-10-2007 17:34:23

Código SQL [-]
SELECT A.CODIGO, A. NOMBRE, SUM(B.CANTIDAD) FROM A, B WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO

La manera correcta de usar SUM,COUNT.. debe estar siempre relacionada con la AGRUPACION( GROUP ) que indiques.. y deben de ser los campos que anteceden a la SUM... en este caso seria asi...

Código SQL [-]
SELECT A.CODIGO, A. NOMBRE, SUM(B.CANTIDAD) FROM A, B WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO,A.NOMBRE

/*  o Tambien puede ser Asi: */


SELECT A.CODIGO, A. NOMBRE, SUM(B.CANTIDAD) FROM A, B WHERE A.CODIGO=B.CODIGO GROUP BY 1,2

/* Si fueran 3  antes del SUM deberian de ser asi.. */

SELECT A.CODIGO, A. NOMBRE, A.APELLIDO SUM(B.CANTIDAD) FROM A, B WHERE A.CODIGO=B.CODIGO GROUP BY 1,2,3


/* Si fueran "N"  antes del SUM deberian de ser asi.. */

SELECT A.CODIGO, A. NOMBRE,campo3 ....   campoN, SUM(B.CANTIDAD) FROM A, B WHERE A.CODIGO=B.CODIGO GROUP BY 1,2,3...,N


Espero te aclare un poco esto...

Gabo 08-10-2007 17:50:00

Cita:

Empezado por pcicom (Mensaje 236920)
Código SQL [-]
SELECT A.CODIGO, A. NOMBRE, SUM(B.CANTIDAD) FROM A, B 
WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO

La manera correcta de usar SUM,COUNT.. debe estar siempre relacionada con la AGRUPACION( GROUP ) que indiques.. y deben de ser los campos que anteceden a la SUM... en este caso seria asi...

Código SQL [-]
SELECT A.CODIGO, A. NOMBRE, SUM(B.CANTIDAD) FROM A, B 
WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO,A.NOMBRE

Espero te aclare un poco esto...

Y si, siguiendo con el ejemplo, no deseo agrupar por el nombre, ¿valdría hacerlo así?

Código SQL [-]
SELECT A.CODIGO, SUM(B.CANTIDAD), A. NOMBRE FROM A, B 
WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO

Voy a probarlo, ya que en realidad sólo necesito agrupar por el código, pero si necesito el resto de los datos.

Gracias por tu respuesta.

Gabo 08-10-2007 17:54:08

Lo acabo de probar y no funciona... :o

Ese es el asunto, que necesito que la consulta obtenga más datos de las tablas...

Seguiré intentándolo. Si doy con la solución les avisaré.

Ivanzinho 10-10-2007 08:59:41

Cita:

Empezado por Gabo (Mensaje 236925)
Y si, siguiendo con el ejemplo, no deseo agrupar por el nombre, ¿valdría hacerlo así?

Código SQL [-]SELECT A.CODIGO, SUM(B.CANTIDAD), A. NOMBRE FROM A, B
WHERE A.CODIGO=B.CODIGO GROUP BY A.CODIGO


Voy a probarlo, ya que en realidad sólo necesito agrupar por el código, pero si necesito el resto de los datos.

Gracias por tu respuesta.

Si no quieres agrupar por el nombre no lo incluyas en la consulta, porque no sé que sentido tiene que quieras sumar un campo y mostrar otro por el que no agrupes, ya que en este caso el sum daría como resultado siempre 1, ya que la consulta te devolvería un registro por cada registro de la tabla.

¿Por qué no nos dices lo que quieres conseguir para poder ayudarte mejor?, porque lo de querer obtener un acumulado por un campo que no agrupas no tiene mucho sentido, ya que el resultado como te dije anteriormente sería siempre 1.

Un saúdo, y espero poder ayudarte.

Lepe 10-10-2007 10:51:33

Es que la función de agrupación funciona así y punto.... no hay más vueltas. Si incluyes una función Sum, avg,etc, debes poner todos los demás campos en el group by

Si por un lado necesitas sumas y además otros campos, realiza 2 consultas, una con el Sum y la otra con los datos que necesitas.

En casos complejos, se puede usar un Procedimiento almacenado (si tu SGBBDD lo permite).


Edito: acabo de ver que usas Interbase, aquí va un ejemplo de un SP de selección:
Código SQL [-]
Create procedure Dame_gente() 
returns
( ELpersonal_nombre  varchar(30),
  ELpersonal_codigo integer,
  ELdemanda_personal numeric(10,2))
as
begin
   for select personal_codigo, sum(demanda_personal)
   from demanda_personal
   group by personal_codigo
   into :ELpersonal_codigo, :ELdemanda_personal do
   begin
   
 /* este es el truco, suponemos que no nos dejaba incluir el nombre porque al usar
    varias tablas lo debíamos de meter en el Group by y no nos daba los resultados
    que esperábamos. Pues lo hacemos en dos partes:
    - Primero hacemos un select con las sumas
    - Después buscamos en las demás tablas los datos para completar el registro que queremos devolver
      con todos los datos juntos
 */
     select personal_nombre 
     from personal
     where codigo_personal = :ELpersonal_codigo
     into :Elpersonal_nombre;
   
     suspend;  //devolvemos todos los parametros que han sido asignados
  end;
end;

Forma de uso:
Código Delphi [-]
  qry1.sql.text := 'select * from Dame_gente';
  qry1.Open;

Como ves en el ejemplo, puedes hacer lo que te apetezca, realmente lo que se hace es construir un registro a mano, como si fuera un puzzle, añadiendo los valores que nos apetezca.


Saludos

Gabo 10-10-2007 11:50:49

Cita:

Empezado por Ivanzinho (Mensaje 237348)
Si no quieres agrupar por el nombre no lo incluyas en la consulta, porque no sé que sentido tiene que quieras sumar un campo y mostrar otro por el que no agrupes, ya que en este caso el sum daría como resultado siempre 1, ya que la consulta te devolvería un registro por cada registro de la tabla.

¿Por qué no nos dices lo que quieres conseguir para poder ayudarte mejor?, porque lo de querer obtener un acumulado por un campo que no agrupas no tiene mucho sentido, ya que el resultado como te dije anteriormente sería siempre 1.

Un saúdo, y espero poder ayudarte.

No veo porqué no tiene sentido la pregunta... :confused:

Si tienes una tabla PERSONAL con dos campos nada más PERSONAL_CODIGO y PERSONAL_NOMBRE y otra TRABAJOS con los campos TRABAJOS_CODIGO, PERSONAL_CODIGO y TRABAJOS_MONTO y deseas obtener un reporte de éste tipo:

Código:


NOMBRE    MONTO
PEDRO    1.023
JOSE      1.114
etc...

En la consulta, necesitas obtener el nombre del personal para desplegarlo, pero la agrupación la debes hacer por el código del personal, ¿o no? Si agrupas por el nombre puede pasar que dos personas se llaman igual y te mezcle sus montos. ¿O estoy equivocado? :confused: Creo que no.

Gabo 10-10-2007 12:01:37

Cita:

Empezado por Lepe (Mensaje 237369)
Es que la función de agrupación funciona así y punto.... no hay más vueltas. Si incluyes una función Sum, avg,etc, debes poner todos los demás campos en el group by

Ese era un punto en el que tenía dudas. No sabía si de alguna manera se podían pedir datos sin agruparlos. Gracias.

Cita:

Empezado por Lepe (Mensaje 237369)
Si por un lado necesitas sumas y además otros campos, realiza 2 consultas, una con el Sum y la otra con los datos que necesitas.

Lamentablemente Interbase (al menos la versión 6) no me permite hacer consultas a consultas, es decir:

Código SQL [-]
Select xyz from (Select xyz from xyz)

Ya que con eso si lo podría lograr.

Cita:

Empezado por Lepe (Mensaje 237369)
En casos complejos, se puede usar un Procedimiento almacenado (si tu SGBBDD lo permite).

Edito: acabo de ver que usas Interbase, aquí va un ejemplo de un SP de selección:

Código SQL [-]
Create procedure Dame_gente()
returns
( ELpersonal_nombre varchar(30),
ELpersonal_codigo integer,
ELdemanda_personal numeric(10,2))
as
begin
for select personal_codigo, sum(demanda_personal)
from demanda_personal
group by personal_codigo
into :ELpersonal_codigo, :ELdemanda_personal do
begin
/* este es el truco, suponemos que no nos dejaba incluir el nombre porque al usar
varias tablas lo debíamos de meter en el Group by y no nos daba los resultados
que esperábamos. Pues lo hacemos en dos partes:
- Primero hacemos un select con las sumas
- Después buscamos en las demás tablas los datos para completar el registro que queremos devolver
con todos los datos juntos
*/
select personal_nombre
from personal
where codigo_personal = :ELpersonal_codigo
into :Elpersonal_nombre;
suspend; //devolvemos todos los parametros que han sido asignados
end;
end;

Forma de uso:



Código Delphi [-]
qry1.sql.text := 'select * from Dame_gente';
qry1.Open;

Como ves en el ejemplo, puedes hacer lo que te apetezca, realmente lo que se hace es construir un registro a mano, como si fuera un puzzle, añadiendo los valores que nos apetezca.


Saludos

[:o] Reconozco que los procedimiento almacenados no son mi fuerte[/:o]
Pero veo que ahí está la solución al problema, asi que...

Lamentablemente hoy no estoy en la oficina, pero mañana, en cuanto llegué, probaré eso y les contaré...

Gracias por la ayuda!!!!

Ivanzinho 10-10-2007 12:17:30

Cita:

Empezado por Gabo (Mensaje 237379)
No veo porqué no tiene sentido la pregunta... :confused:

Si tienes una tabla PERSONAL con dos campos nada más PERSONAL_CODIGO y PERSONAL_NOMBRE y otra TRABAJOS con los campos TRABAJOS_CODIGO, PERSONAL_CODIGO y TRABAJOS_MONTO y deseas obtener un reporte de éste tipo:

Código:


NOMBRE    MONTO
PEDRO    1.023
JOSE      1.114
etc...

En la consulta, necesitas obtener el nombre del personal para desplegarlo, pero la agrupación la debes hacer por el código del personal, ¿o no? Si agrupas por el nombre puede pasar que dos personas se llaman igual y te mezcle sus montos. ¿O estoy equivocado? :confused: Creo que no.

Si agrupas sólo por nombre pasaría lo que tu dices, pero para eso tienes que agrupar por código y nombre. Es que no entiendo por qué no quieres incluir el nombre en el group by.

Te va a devolver los mismos registros agrupar por código sólo que agrupar por codigo y nombre, pero si quieres incluir el nombre en la select tiene que incluirlo tambien en el group by.

Para lo que tu quieres no te hace falta usar un procedimiento almacenado

Un saúdo.

Gabo 10-10-2007 13:20:35

Cita:

Empezado por Ivanzinho (Mensaje 237386)
Si agrupas sólo por nombre pasaría lo que tu dices, pero para eso tienes que agrupar por código y nombre. Es que no entiendo por qué no quieres incluir el nombre en el group by.

Te va a devolver los mismos registros agrupar por código sólo que agrupar por codigo y nombre, pero si quieres incluir el nombre en la select tiene que incluirlo tambien en el group by.

Para lo que tu quieres no te hace falta usar un procedimiento almacenado

Un saúdo.

Creo que lo que pasa es que estoy mal con los conceptos, el group by sólo ordena los registros no hace el resumen de ellos, bajo esa premisa, no debería tener problemas al pedir lo que me dices.

Prometo probarlo mañana en cuanto llegue a la oficina.

Gracias!!!!

Ivanzinho 10-10-2007 13:34:53

Creo que estás confundiendo el group by con el order by.

El group by agrupa los registros de una select por los campos indicados e decir si tienes :
Código:

Personal.id  Personal.nombre  Trabajos.monto
1              Breogan              100
1              Breogan              50
2              Brais                100
3              Uxía                  150
4              Saleta                25
3              Uxía                  10

y agrupas por Personal.id y Personal.Nombre, realizando la suma de los montos obtendras lo siguiente
Código:

Personal.id  Personal.nombre  Trabajos.monto
1              Breogan              150
2              Brais                100
3              Uxía                  160
4              Saleta                25

El group by lo puedes combinar con el order by para ordenar por los campos que desees.

Un saúdo

Gabo 10-10-2007 14:04:37

Cita:

Empezado por Ivanzinho (Mensaje 237404)
Creo que estás confundiendo el group by con el order by.

Bueno no es ese en realidad mi problema, creo que en mi mensaje anterior no me explique bien. :p

Cita:

Empezado por Ivanzinho (Mensaje 237404)
El group by agrupa los registros de una select por los campos indicados e decir si tienes :

y agrupas por Personal.id y Personal.Nombre, realizando la suma de los montos obtendras lo siguiente

El group by lo puedes combinar con el order by para ordenar por los campos que desees.

Un saúdo

Esto si que no lo tengo muy claro, pensaba que en un caso como éste:

Código:

Personal.id  Personal.nombre  Trabajos.monto
1              Breogan              100
1              Breogan              50
2              Brais                100
3              Uxía                  150
4              Saleta                25
5              Uxía                  10    <--- Nota que he cambiado el código

igual me daría un resultado como éste, por haber agrupado por el nombre:
Código:

Personal.id  Personal.nombre  Trabajos.monto
1              Breogan              150
2              Brais                100
3              Uxía                  160
4              Saleta                25

Pero ahora que lo pienso no es lógico, lo probaré mañana mismo...

Ivanzinho 10-10-2007 15:17:37

Pero por eso tienes que agrupar por nombre y código, así se seleccionarán los distintos valores de la tupla (codigo, nombre), es decir, en el ejemplo que pusiste tu (3, Uxía) <> (5, Uxía), por lo que la consulta devolvería dos registros y no sólo uno.

Un saúdo.

pcicom 10-10-2007 17:29:59

A Veces la Mejor Manera de APRENDER es un LEER e intentar comprender.

Cita:

PCICOM
La manera correcta de usar SUM,COUNT.. debe estar siempre relacionada con la AGRUPACION( GROUP ) que indiques.. y deben de ser los campos que anteceden a la SUM...
::
Cita:

Empezado por Lepe
Es que la función de agrupación funciona así y punto.... no hay más vueltas. Si incluyes una función Sum, avg,etc, debes poner todos los demás campos en el group by
::

Va de Nuez...

Puedes hacer una CONSULTA

Código SQL [-]
CREATE VIEW vTOTALES (
      NUMERO
      TOTAL
)
AS
 SELECT NUMERO,SUM(IMPORTE) FROM tabla GROUP BY NUMERO;

Ya entonces creada tu vista puedes jugar con ELLA..

Código SQL [-]

    SELECT a.NUMERO,a.TOTAL,personal.NOMBRE FROM vTOTALES a
        LEFT JOIN personal ON a.NUMERO=personal.NUMERO
    WHERE 

Gabo 11-10-2007 12:19:27

Cita:

Empezado por pcicom (Mensaje 237478)
A Veces la Mejor Manera de APRENDER es un LEER e intentar comprender.

Si eso hago, leo e intento comprender.;)

Lo que me dijiste en un principio, lo entendí claramente, pero insistí un poco porque hasta ese momento no sabía que agrupando por varios campos no se mezclaban los registros y quería saber si existía alguna manera especial de hacer lo que pretendía.

Claro, cuando Lepe me dijo:

Cita:

Es que la función de agrupación funciona así y punto.... no hay más vueltas. Si incluyes una función Sum, avg,etc, debes poner todos los demás campos en el group by
,pensé: "entonces es que no se puede y tendré que verlo de otra forma".

Hasta que Ivanzinho me aclaro el otro punto que desconocía.

Gracias por la ayuda, ya que me ha servido para aclarar algunos conceptos que no tenía claros. :)

Gabo 11-10-2007 12:23:47

Cita:

Empezado por Lepe (Mensaje 237369)
En casos complejos, se puede usar un Procedimiento almacenado (si tu SGBBDD lo permite).

A las finales lo he resuelto de la forma que me sugirió Ivanzinho, pero de todas maneras lo dicho lo mantengo... lo implementaré con el procedimiento, aunque sólo será para aprendizaje y ocuparlo cuando lo necesite.

Gracias por tu ejemplo, que me servirá para aprenderlo. :)

Gabo 11-10-2007 12:28:04

Cita:

Empezado por Ivanzinho (Mensaje 237423)
Pero por eso tienes que agrupar por nombre y código, así se seleccionarán los distintos valores de la tupla (codigo, nombre), es decir, en el ejemplo que pusiste tu (3, Uxía) <> (5, Uxía), por lo que la consulta devolvería dos registros y no sólo uno.

Un saúdo.

Como habrás visto, ya lo he probado y llevas toda la razón. ¡Gracias por aclararme ese punto! :)

No más por eso dejaré que seas milenario primero... :D:D:D
El que no entiende, haca clic aquí.

Lepe 11-10-2007 14:52:25

... Como veis... yo también aprendo de vosotros :rolleyes:

Saludos

Ivanzinho 11-10-2007 15:30:48

Cita:

Empezado por Gabo (Mensaje 237748)
No más por eso dejaré que seas milenario primero... :D:D:D
El que no entiende, haca clic aquí.

No te queda otra :D.

Cita:

Empezado por Gabo (Mensaje 237748)
Como habrás visto, ya lo he probado y llevas toda la razón. ¡Gracias por aclararme ese punto! :)

Me alegro que te haya servido.

Un saúdo.


La franja horaria es GMT +2. Ahora son las 21:35:49.

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