Consulta SQL

22/11/2004 - 02:50 por Rafael Aguero | Informe spam
Una consulta de un amigo Foxero Peru:

Tengo una pregunta con respecto a SQL
Tengo la tabla Articulos:

Articulo, Descripcion, Proveedor
201 Remera 1
202 Pantalon 2
Tabla Proveedor:

Numero, Proveedor
1 Falsa S.A.
2 Punga S.R.L.

Tabla Compra:

Ingreso, Numart, Artcompra, Montocompra
1 201 20 $200
2 202 15 $360
3 202 30 $720
Tabla Venta:

Ingreso, Numero, Vendido, Montovendido
209567 202 3 $96
457890 202 8 $256
678342 201 7 $84
689345 202 15 $480

Quiero averiguar por cada articulo su descripción, el proveedor, total
comprados, total de monto de compra, Total vendido y monto total de la
venta.

La sentencia es esta

SELECT Articulos.articulo, Articulos.descripcion, Proveedor.Proveedor,
sum(Compra.Artcompra), sum(Compra.Montocompra), sum(Venta.Vendido),
sum(Venta.Montovendido);
FROM bd1!Articulos INNER JOIN bd1!proveedor ON Articulos.Proveedor Proveedor.Numero;
INNER JOIN bd1!Compra ON Articulos.articulo = Compra.Numart;
INNER JOIN bd1!Venta ON Articulos.articulo = Venta.numero ;
GROUP BY Articulos.articulo;
ORDER BY Articulos.articulo;

El resultado deberia ser:

201 Remera Falsa S.A. 20 $200 7 $84
202 Pantalon Punga S.R.L. 45 $1080 26 $832

Pero, me muestra esto:

201 Remera Falsa S.A. 20 $200 7 $84
202 Pantalon Punga S.R.L. 135 $3240 52 $1664

Me multiplica por 3 -que son los registros de Venta- a 45 y $1080, y por 2
que son los registros de Compra- a 26 y $832
¿En que estoy fallando en la sentencia?
Bueno, perdón por lo extenso. Desde ya muchas gracias.

EviSoft2004

-
PortalFox :: Nada corre como un zorr
http://www.portalfox.co

PortalFox - NNTP Forum Gatewa

Preguntas similare

Leer las respuestas

#1 Esparta Palma
22/11/2004 - 09:40 | Informe spam
Ufff, me pareció que aunque fué extenso, se explica muy bien qué es lo que
quieres hacer, pues bien, para resolver tu consulta se deberá atacar de
otro modo. A continuación dejaré el cómo se haría en cualquier versión de
VFP.

Así como lo pones, el SELECT-SQL está haciendo una proyección transversal,
por que hay dos pares de uniones que es ahí donde se decide cuáles
artículos van con que compra o venta, así pues, dicha consulta necesita un
"poquito de ayuda", ¿cómo se logra eso?, simplemente haciendo consultas
intermedias para poder seleccionar lo que quieras:

1.- Una consulta que nos de los artículos, sus respectivas ventas y
montos de ventas. Mas un identificador que nos diga que son las ventas.

SELECT Numero AS cArticulo, Artcompra as nArticulos, ;
Montocompra as yMonto, .T. AS lVenta ;
FROM Ventas

2.- Otra consulta que haga lo mismo pero con entidad compras más un
identificador de que es compra (o no venta).

SELECT Numart as cArticulo, Vendido AS nArticulos,;
Montovendido AS yMonto, .F. AS lVenta ;
FROM Compras

3.- Ahora podemos unir las dos consultas:

SELECT Numart AS cArticulo, Artcompra as nArticulos, ;
Montocompra as yMonto, .F. AS lVenta ;
FROM Compras ;
UNION ;
SELECT Numero as cArticulo, Vendido AS nArticulos,;
Montovendido AS yMonto, .T. AS lVenta ;
FROM Ventas ;
INTO CURSOR cResumen

4.- A continuación hacemos la agrupación distinguiendo las compras y las
ventas:

SELECT cArticulo, ;
SUM(NOT lVenta, nArticulo, 0)+000000 as nCompras,;
SUM(NOT lVenta, yMonto,0)+$0 as yMontoCompras,;
SUM(lVenta,nArticulo,0)+0000000 as nVentas,;
SUM(lVenta,nArticulo,0)+$0 as yMontoVentas ;
FROM cResumen ;
GROUP BY cArticulo ;
INTO CURSOR cAgrupado


5.- Ahora hacemos una proyección incluyendo los datos que fueren
necesarios:

SELECT cAgrupado.cArticulo, Articulos.Descripcion,;
Proveedor.Proveedor, nCompras, yMontoCompras, ;
nVentas, yMontoVentas ;
FROM cAgrupado ;
INNER JOIN Articulos ON Articulos.Articulo = cAgrupado.cArticulo ;
INNER JOIN Proveedor ON Proveedor.Numero = Articulos.Proveedor ;
GROUP BY cArticulo, Articulos.Descripcion, Proveedor.Proveedor ;
INTO CURSOR cReport

5b.- Puedes simplificar los dos pasos anteriores haciendo la proyección y
agrupación en un solo paso:

SELECT cArticulo, ;
Articulo.descripcion,;
Proveedor.proveedor ,;
SUM(IIF(NOT lVenta, nArticulos, 0))+000000 as nCompras,;
SUM(IIF(NOT lVenta, yMonto,0))+$0 as yMontoCompras,;
SUM(IIF(lVenta,nArticulos,0))+0000000 as nVentas,;
SUM(IIF(lVenta,yMonto,0))+$0 as yMontoVentas ;
FROM cResumen ;
INNER JOIN Articulo ON Articulo.Articulo = cResumen.carticulo
;
INNER JOIN Proveedor ON Proveedor.Numero = Articulo.Proveedor ;
GROUP BY cArticulo,Articulo.descripcion,Proveedor.proveedor ;
INTO CURSOR cAgrupado
BROWSE


Esto es mas o menos lo que debería hacerse, es un error común el pensar
que todo se puede hacer con una sola consulta SELECT-SQL, a veces hay que
utilizar subconsultas, y no solo proyecciones directas. Notese que he
separado algunas consultas, y a veces unirlas, el cuán separado lo dejas
dependerá de tu caso específico, ya que entre más pasos intermedios dejes,
puedes enviar más mensajes a tu usuario indicándo qué algo se está
haciendo, ya que en cuanto el número de datos empiece a crecer puede ser
una posibilidad a que se vaya tardando cada vez más, por ejemplo, si lo
pruebas con 1000 datos... será rapidísimo, pero en cuanto llegues a los
millones de registros, se tardará, y muchos usuarios sienten que dos o
tres segundos es un mundo, y mientras se tarda los puedes animar un
poquito, así no se desesperarán y empiecen a "tronar" tu aplicación porque
"ya no respondía" ...

Otra cosa que quería comentar es que la consulta que te recomiendo (basado
en subconsultas) servirá también en el caso que tengas productos
comprados, pero no vendidos, o viceversa.

Me tomé la libertad de hacer ésto mismo pero como práctica de lo que se
pudiere hacer con VFP9 y la consulta quedaría más o menos así:

SELECT cArticulo,;
Articulo.descripcion as cDesc, ;
Proveedor.proveedor as cProveedor,;
CAST(SUM(IIF(NOT lVenta,nArticulos,0)) as int) as nCompras,;
CAST(SUM(IIF(NOT lVenta,yMonto,0)) as y) as yMontoCompras,;
CAST(SUM(IIF(lVenta,nArticulos,0)) as int) as nVentas,;
CAST(SUM(IIF(lVenta,yMonto,0)) as y) as yMontoVentas ;
FROM ( SELECT Numart AS cArticulo, Artcompra as nArticulos,;
Montocompra as yMonto,.F. AS lVenta ;
FROM Compra ;
UNION ;
SELECT Numero as cArticulo,Vendido AS nArticulos,;
Montovendido AS yMonto,.T. AS lVenta ;
FROM Ventas ) as cResumen ;
INNER JOIN Articulo ON Articulo.articulo = cResumen.cArticulo ;
INNER JOIN Proveedor ON Proveedor.numero = Articulo.proveedor ;
GROUP BY cArticulo,Articulo.descripcion,Proveedor.proveedor


Esto para ilustrar un poco algunas de las bondades de ésta nueva (y
próxima) versión, ahora ya se pueden hacer subconsultas, ¿Que ventajas nos
dá ésto?, pues resulta que la anterior cláusula funcionará con BD de VFP,
y será mucho más fácil el transformarle cuando pudiera llegar el día de un
posible upgrade hacia un servidor de base de datos que sea más compatible
con ANSI SQL 92.

Espero te sirva.

Una consulta de un amigo Foxero Peru:

Tengo una pregunta con respecto a SQL
Tengo la tabla Articulos:

Articulo, Descripcion, Proveedor
201 Remera 1
202 Pantalon 2
Tabla Proveedor:

Numero, Proveedor
1 Falsa S.A.
2 Punga S.R.L.

Tabla Compra:

Ingreso, Numart, Artcompra, Montocompra
1 201 20 $200
2 202 15 $360
3 202 30 $720
Tabla Venta:

Ingreso, Numero, Vendido, Montovendido
209567 202 3 $96
457890 202 8 $256
678342 201 7 $84
689345 202 15 $480

Quiero averiguar por cada articulo su descripción, el proveedor, total
comprados, total de monto de compra, Total vendido y monto total de la
venta.

La sentencia es esta

SELECT Articulos.articulo, Articulos.descripcion, Proveedor.Proveedor,
sum(Compra.Artcompra), sum(Compra.Montocompra), sum(Venta.Vendido),
sum(Venta.Montovendido);
FROM bd1!Articulos INNER JOIN bd1!proveedor ON Articulos.Proveedor >Proveedor.Numero;
INNER JOIN bd1!Compra ON Articulos.articulo = Compra.Numart;
INNER JOIN bd1!Venta ON Articulos.articulo = Venta.numero ;
GROUP BY Articulos.articulo;
ORDER BY Articulos.articulo;

El resultado deberia ser:

201 Remera Falsa S.A. 20 $200 7 $84
202 Pantalon Punga S.R.L. 45 $1080 26 $832

Pero, me muestra esto:

201 Remera Falsa S.A. 20 $200 7 $84
202 Pantalon Punga S.R.L. 135 $3240 52 $1664

Me multiplica por 3 -que son los registros de Venta- a 45 y $1080, y por 2
que son los registros de Compra- a 26 y $832
¿En que estoy fallando en la sentencia?
Bueno, perdón por lo extenso. Desde ya muchas gracias.

EviSoft2004



ž,ø€º°`°º€ø,žž,ø€º°`°º€ø,žž,ø€º°`°º€ø,žž,ø€º°`°º
Espartaco Palma Martínez
SysOp PortalFox.com
Acapulco, México
email:mexicoSINSPAM[Arroba]portalfox.com


PortalFox :: Nada corre como un zorro
http://www.portalfox.com

PortalFox - NNTP Forum Gateway
Respuesta Responder a este mensaje
#2 Esparta Palma
22/11/2004 - 09:46 | Informe spam
SELECT cResumen.Articulo,;
CAST(Articulo.descripcion AS c(10)) as cDesc , ;
CAST(Proveedor.proveedor AS c(10)) AS cProveedor,;
CAST(SUM(IIF(NOT lVenta,cResumen.Vendido,0)) AS int)as nCompras,;
CAST(SUM(IIF(NOT lVenta,cResumen.MontoVendido,0)) as int)as yCompras, ;

CAST(SUM(IIF(lVenta,cResumen.Vendido,0)) AS int)as nVentas,;
CAST(SUM(IIF(lVenta,cResumen.MontoVendido,0)) as int)as yVentas ;
FROM ;
(SELECT Articulo.articulo,Vendido,MontoVendido,.T. as lVenta ;
FROM Articulo LEFT JOIN Ventas ON Articulo.articulo Ventas.numart ;
UNION ;
SELECT Articulo.articulo,ArtCompra,MontoCompra,.F. as lVenta ;
FROM Articulo LEFT JOIN Compra ON Articulo.articulo Compra.numart) cResumen ;
INNER JOIN Articulo ON Articulo.articulo = cResumen.Articulo ;
INNER JOIN Proveedor ON Proveedor.numero = Articulo.proveedor ;
GROUP BY cResumen.Articulo,Articulo.descripcion,Proveedor.proveedor


Ufff, me pareció que aunque fué extenso, se explica muy bien qué es lo que
quieres hacer, pues bien, para resolver tu consulta se deberá atacar de
otro modo. A continuación dejaré el cómo se haría en cualquier versión de
VFP.

Así como lo pones, el SELECT-SQL está haciendo una proyección transversal,
por que hay dos pares de uniones que es ahí donde se decide cuáles
artículos van con que compra o venta, así pues, dicha consulta necesita un
"poquito de ayuda", cómo se logra eso, simplemente haciendo consultas
intermedias para poder seleccionar lo que quieras:

1.- Una consulta que nos de: los artículos y sus respectivas sumas de
ventas y montos de ventas. Mas un identificador que nos diga que son las
ventas.

SELECT Numart AS cArticulo, Artcompra as nArticulos, ;
Montocompra as yMonto, .F. AS lVenta ;
FROM Compras

2.- Otra consulta que haga lo mismo pero con las compras más un
identificador de que es compra.

SELECT Numero as cArticulo, Vendido AS nArticulos,;
Montovendido AS yMonto, .T. AS lVenta ;
FROM Ventas

3.- Ahora podemos unir las dos consultas:

SELECT Numart AS cArticulo, Artcompra as nArticulos, ;
Montocompra as yMonto, .F. AS lVenta ;
FROM Compras ;
UNION ;
SELECT Numero as cArticulo, Vendido AS nArticulos,;
Montovendido AS yMonto, .T. AS lVenta ;
FROM Ventas ;
INTO CURSOR cResumen

4.- A continuación hacemos la agrupación distinguiendo las compras y las
ventas:

SELECT cArticulo, ;
SUM(NOT lVenta, nArticulo, 0)+000000 as nCompras,;
SUM(NOT lVenta, yMonto,0)+$0 as yMontoCompras,;
SUM(lVenta,nArticulo,0)+0000000 as nVentas,;
SUM(lVenta,nArticulo,0)+$0 as yMontoVentas ;
FROM cResumen ;
GROUP BY cArticulo ;
INTO CURSOR cAgrupado


5.- Ahora hacemos una proyección incluyendo los datos que fueren
necesarios:

SELECT cAgrupado.cArticulo, Articulos.Descripcion,;
Proveedor.Proveedor, nCompras, yMontoCompras, ;
nVentas, yMontoVentas ;
FROM cAgrupado ;
INNER JOIN Articulos ON Articulos.Articulo = cAgrupado.cArticulo ;
INNER JOIN Proveedor ON Proveedor.Numero = Articulos.Proveedor ;
GROUP BY cArticulo, Articulos.Descripcion, Proveedor.Proveedor ;
INTO CURSOR cReport

5b.- Puedes simplificar los dos pasos anteriores haciendo la proyección y
agrupación en un solo paso:

SELECT cArticulo, ;
Articulo.descripcion,;
Proveedor.proveedor ,;
SUM(IIF(NOT lVenta, nArticulos, 0))+000000 as nCompras,;
SUM(IIF(NOT lVenta, yMonto,0))+$0 as yMontoCompras,;
SUM(IIF(lVenta,nArticulos,0))+0000000 as nVentas,;
SUM(IIF(lVenta,yMonto,0))+$0 as yMontoVentas ;
FROM cResumen ;
INNER JOIN Articulo ON Articulo.Articulo = cResumen.carticulo ;
INNER JOIN Proveedor ON Proveedor.Numero = Articulo.Proveedor ;
GROUP BY cArticulo,Articulo.descripcion,Proveedor.proveedor ;
INTO CURSOR cAgrupado
BROWSE


Esto es mas o menos lo que debería hacerse, es un error común el pensar
que todo se puede hacer con una sola consulta SELECT-SQL, a veces hay que
utilizar subconsultas, y no solo proyecciones directas. Notese que he
separado algunas consultas, y a veces unirlas, el cuán separado lo dejas
dependerá de tu caso específico, ya que entre más pasos intermedios dejes,
puedes enviar más mensajes a tu usuario indicándo qué algo se está
haciendo, ya que en cuanto el número de datos empiece a crecer puede ser
una posibilidad a que se vaya tardando cada vez más, por ejemplo, si lo
pruebas con 1000 datos... será rapidísimo, pero en cuanto llegues a los
millones de registros, se tardará, y muchos usuarios sienten que dos o
tres segundos es un mundo, y mientras se tarda los puedes animar un
poquito, así no se desesperarán y empiecen a "tronar" tu aplicación porque
"ya no respondía" ...

Otra cosa que quería comentar es que la consulta que te recomiendo (basado
en subconsultas) servirá también en el caso que tengas productos
comprados, pero no vendidos, o viceversa.

Me tomé la libertad de hacer ésto mismo pero como práctica de lo que se
pudiere hacer con VFP9 y la consulta quedaría más o menos así:

SELECT cArticulo,;
Articulo.descripcion as cDesc, ;
Proveedor.proveedor as cProveedor,;
CAST(SUM(IIF(NOT lVenta,nArticulos,0)) as int) as nCompras,;
CAST(SUM(IIF(NOT lVenta,yMonto,0)) as y) as yMontoCompras,;
CAST(SUM(IIF(lVenta,nArticulos,0)) as int) as nVentas,;
CAST(SUM(IIF(lVenta,yMonto,0)) as y) as yMontoVentas ;
FROM ( SELECT Numart AS cArticulo, Artcompra as nArticulos,;
Montocompra as yMonto,.F. AS lVenta ;
FROM Compra ;
UNION ;
SELECT Numero as cArticulo,Vendido AS nArticulos,;
Montovendido AS yMonto,.T. AS lVenta ;
FROM Ventas ) as cResumen ;
INNER JOIN Articulo ON Articulo.articulo = cResumen.cArticulo ;
INNER JOIN Proveedor ON Proveedor.numero = Articulo.proveedor ;
GROUP BY cArticulo,Articulo.descripcion,Proveedor.proveedor


Esto para ilustrar un poco algunas de las bondades de ésta nueva (y
próxima) versión, ahora ya se pueden hacer subconsultas, ¿Que ventajas nos
dá ésto?, pues resulta que la anterior cláusula funcionará con BD de VFP,
y será mucho más fácil el transformarle cuando pudiera llegar el día de un
posible upgrade.

Una consulta de un amigo Foxero Peru:

Tengo una pregunta con respecto a SQL
Tengo la tabla Articulos:

Articulo, Descripcion, Proveedor
201 Remera 1
202 Pantalon 2
Tabla Proveedor:

Numero, Proveedor
1 Falsa S.A.
2 Punga S.R.L.

Tabla Compra:

Ingreso, Numart, Artcompra, Montocompra
1 201 20 $200
2 202 15 $360
3 202 30 $720
Tabla Venta:

Ingreso, Numero, Vendido, Montovendido
209567 202 3 $96
457890 202 8 $256
678342 201 7 $84
689345 202 15 $480

Quiero averiguar por cada articulo su descripción, el proveedor, total
comprados, total de monto de compra, Total vendido y monto total de la
venta.

La sentencia es esta

SELECT Articulos.articulo, Articulos.descripcion, Proveedor.Proveedor,
sum(Compra.Artcompra), sum(Compra.Montocompra), sum(Venta.Vendido),
sum(Venta.Montovendido);
FROM bd1!Articulos INNER JOIN bd1!proveedor ON Articulos.Proveedor >Proveedor.Numero;
INNER JOIN bd1!Compra ON Articulos.articulo = Compra.Numart;
INNER JOIN bd1!Venta ON Articulos.articulo = Venta.numero ;
GROUP BY Articulos.articulo;
ORDER BY Articulos.articulo;

El resultado deberia ser:

201 Remera Falsa S.A. 20 $200 7 $84
202 Pantalon Punga S.R.L. 45 $1080 26 $832

Pero, me muestra esto:

201 Remera Falsa S.A. 20 $200 7 $84
202 Pantalon Punga S.R.L. 135 $3240 52 $1664

Me multiplica por 3 -que son los registros de Venta- a 45 y $1080, y por 2
que son los registros de Compra- a 26 y $832
¿En que estoy fallando en la sentencia?
Bueno, perdón por lo extenso. Desde ya muchas gracias.

EviSoft2004



ž,ø€º°`°º€ø,žž,ø€º°`°º€ø,žž,ø€º°`°º€ø,žž,ø€º°`°º
Espartaco Palma Martínez
SysOp PortalFox.com
Acapulco, México
email:mexicoSINSPAM[Arroba]portalfox.com


PortalFox :: Nada corre como un zorro
http://www.portalfox.com

PortalFox - NNTP Forum Gateway
Respuesta Responder a este mensaje
#3 Rafael Aguero
23/11/2004 - 02:33 | Informe spam
Tienes mucha razon amigo Esparta Palma, no todos los SELECTSQL se podran
hacer directamente, claro q las nuevas versiones siempre te haran faciltar
mejor las cosas, lo indicado es crear cursores temporales para buscar la
consulta final ideal a lo q se requiere la administracion a veces cuando
lo piden, yno saben lo complejo q resutal ser obtener este tipo de
resultados.
Muchos exitos y gracias otra vez.

Lic. Rafael Aguero Ynca.

EviSoft2004

-
PortalFox :: Nada corre como un zorr
http://www.portalfox.co

PortalFox - NNTP Forum Gatewa
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida