NO USAR CURSOR SQL2000

04/07/2007 - 04:52 por Miguel Angel Juárez Herrera | Informe spam
Saludos amigos.
Pues estoy tratando de cambiar mi forma de programar con cursores.
Tengo un ejemplo que no encuentro como resolverlo, espero alguien me pueda
auxiliar.
El escenario es el siguiente, tengo una tabla con una clave de cliente,
nombres, y total de ventas.
obtengo el valor del total de las ventas y obtengo el total del 80% y del 20%
Los clientes cuyas ventas representen el 80% del total del ingreso son "a" y
los que representan el 20% son "B"
Yo con un cursor ordeno descendentemente por el campo de totalventas, y así
recorro cliente por cliente y voy sumando desde el que mas vende hasta el que
menos y voy poniendoles "A" hasdta completar el 80%, luego la comparación del
ultimo 20 % s eles pone "b"
y mi cursor queda así:

select @total = sum(mesactualacumulado) from Rpt600AB
set @a = @total * .8
set @b = @total * .2
set @total = 0
DECLARE CurAB CURSOR FORWARD_ONLY FOR
select ruta, nud, mesactualacumulado from Rpt600AB order by
mesactualacumulado desc, vtamesAnt1 desc, vtamesAnt2
open CurAB
FETCH NEXT FROM CurAB INTO @ruta, @nud,@mesactualacumulado
WHILE @@FETCH_STATUS = 0
BEGIN
set @total = @total + @mesactualacumulado
if @total <= @a
begin
update Rpt600AB set tipocliente = '80' where nud =
@nud and ruta = @ruta and mesactualacumulado = @mesactualacumulado
end
else
if (@total <= (@a + @b)) and (@total > @a)
begin
update Rpt600AB set tipocliente = '20' where
nud = @nud and ruta = @ruta and mesactualacumulado = @mesactualacumulado
end
FETCH NEXT FROM CurAB INTO @ruta,
@nud,@mesactualacumulado
END
CLOSE CurAB
DEALLOCATE CurAB


existe alguna manera de no hacerlo por cursor?..
Gracias.




Miguel Angel Juárez Herrera.
Programador (NET, VB6 y SQL 2000).
Sistemas GEUSA

Preguntas similare

Leer las respuestas

#1 Carlos M. Calvelo
04/07/2007 - 11:48 | Informe spam
On 4 jul, 04:52, Miguel Angel Juárez Herrera
<mjuarezh36(antispam)@yahoo.com.mx> wrote:
Saludos amigos.
Pues estoy tratando de cambiar mi forma de programar con cursores.
Tengo un ejemplo que no encuentro como resolverlo, espero alguien me pueda
auxiliar.
El escenario es el siguiente, tengo una tabla con una clave de cliente,
nombres, y total de ventas.
obtengo el valor del total de las ventas y obtengo el total del 80% y del 20%
Los clientes cuyas ventas representen el 80% del total del ingreso son "a" y
los que representan el 20% son "B"
Yo con un cursor ordeno descendentemente por el campo de totalventas, y así
recorro cliente por cliente y voy sumando desde el que mas vende hasta el que
menos y voy poniendoles "A" hasdta completar el 80%, luego la comparación del
ultimo 20 % s eles pone "b"
y mi cursor queda así:




Se puede hacer. Pero como a mi me gusta saber 'qué hacer'
antes de 'cómo hacerlo' :-) ... tengo una pregunta:

Si sumando.. sumando... se acaba el 80% del total y los clientes
siguientes tienen un total de ventas igual a los anteriores, con qué
criteria se determina cuales son tipo 'A' y cuales son tipo 'B'?
Un caso extremo: tenemos 10 registros todos con un total
de ventas de 10 euros. Cuales son del tip o 'A' y cuales son
del tipo 'B'?

Saludos,
Carlos
Respuesta Responder a este mensaje
#2 Carlos M. Calvelo
04/07/2007 - 15:41 | Informe spam
Hola Miguel,

On 4 jul, 04:52, Miguel Angel Juárez Herrera
<mjuarezh36(antispam)@yahoo.com.mx> wrote:
Saludos amigos.
Pues estoy tratando de cambiar mi forma de programar con cursores.
Tengo un ejemplo que no encuentro como resolverlo, espero alguien me pueda
auxiliar.
El escenario es el siguiente, tengo una tabla con una clave de cliente,
nombres, y total de ventas.
obtengo el valor del total de las ventas y obtengo el total del 80% y del 20%
Los clientes cuyas ventas representen el 80% del total del ingreso son "a" y
los que representan el 20% son "B"
Yo con un cursor ordeno descendentemente por el campo de totalventas, y así
recorro cliente por cliente y voy sumando desde el que mas vende hasta el que
menos y voy poniendoles "A" hasdta completar el 80%, luego la comparación del
ultimo 20 % s eles pone "b"



<...>


existe alguna manera de no hacerlo por cursor?..
Gracias.




Por si todavía no habías considerado lo que pregunto en el otro
post, estudia el siguiente ejemplo y las diferencias entre las
dos consultas.
A mi me parece más lógico lo que pasa en la segunda; todos los
clientes con un total de ventas de 5,00 pertenecen als mismo tipo.

Después lo puedes adaptar a tu situación.

Saludos,
Carlos


create table cliente (
idCliente int not null primary key,
totalVentas money not null
)

insert into cliente values (1,3)
insert into cliente values (2,2)
insert into cliente values (3,5)
insert into cliente values (4,5)
insert into cliente values (5,5)
insert into cliente values (6,5)
insert into cliente values (7,10)
insert into cliente values (8,25)
insert into cliente values (9,40)

select a.idCliente,a.totalVentas,sum(b.totalVentas) as runningTotal,
case when sum(b.totalVentas) >= (select sum(totalVentas) * 0.2 from
cliente)
then 'A' else 'B' end as tipoCliente
from cliente a inner join cliente b on a.totalVentas>b.totalVentas or
(a.totalVentas=b.totalVentas and a.idCliente<=b.idCliente)
group by a.idCliente, a.totalVentas
order by a.totalVentas asc, a.idCliente desc

select a.idCliente,a.totalVentas,sum(b.totalVentas) as runningTotal,
case when sum(b.totalVentas) >= (select sum(totalVentas) * 0.2 from
cliente)
then 'A' else 'B' end as tipoCliente
from cliente a inner join cliente b on b.totalVentas<=a.totalVentas
group by a.idCliente, a.totalVentas
order by a.totalVentas asc, a.idCliente desc

drop table cliente
Respuesta Responder a este mensaje
#3 Ricardo Passians
04/07/2007 - 20:03 | Informe spam

existe alguna manera de no hacerlo por cursor?..





Sí, debe haberla, pero en un caso tan peculiar como ése claramente orientado
a registros, yo no me complicaría la vida. Lo resolvería trayéndome a la
aplicación cliente el conjunto ordenado por volumen de ventas y luego lo
post-procesaría en un datatable para agregarle el estatus 'A' o 'B'.

Saludos,

Ricardo Passians
Respuesta Responder a este mensaje
#4 Alejandro Mesa
04/07/2007 - 21:50 | Informe spam
Hola Miguel,

Hasta la version 2005 no contamos con una forma sencilla de llevar sumas
corrientes (yo no se la traduccion exacta al espaniol de "running totals") y
hasta ahora las soluciones orientadas a conjuntos tienden a ser mas costosa
que la que usa cursores.

Puedes comparar la version que tienes con:

create table #t (
cliente_id int,
totalventas money
)

insert into #t values(1, 10)
insert into #t values(2, 10)
insert into #t values(3, 20)
insert into #t values(4, 5)
insert into #t values(6, 5)
insert into #t values(7, 12)
insert into #t values(8, 8)
insert into #t values(9, 10)
insert into #t values(10, 3)
insert into #t values(11, 3)
insert into #t values(12, 2)
insert into #t values(13, 2)

declare @p numeric(5, 2)

set @p = 80

;with cte
as
(
select
cliente_id,
totalventas,
(totalventas * 100.) / sum(totalventas) over() as totalventas_percent,
row_number() over(order by totalventas desc) as rn
from
#t
),
running_total
as
(
select
rn,
cliente_id,
totalventas,
totalventas_percent,
(select sum(totalventas_percent) from cte as b where b.rn <= a.rn) as
running_percent
from
cte as a
)
select
rn,
cliente_id,
totalventas,
totalventas_percent,
running_percent,
case when running_percent <= @p then 'A' else 'B' end as tipo_cliente
from
running_total
order by
rn

drop table #t
go

Por esta razon, Itzik Ben-Gan, considerado como Guru de T-SQL y MVP de SQL
Server, en conjunto con Sujata Mehta, escribieron un articulo a fondo sobre
este tema, proponiendo a Microsoft que la nueva clausula OVER sea mejorada.
En ese articulo se hace un analizis de los planes de ejecucion de la solucion
que usa cursores y la que esta orientada a conjuntos.

http://www.sql.co.il/books/insidets...ources.htm

El primer link bajo "Whitepapers".

"OVER Clause and Ordered Calculations - Feature Enhancements Request by
Itzik Ben-Gan and Sujata Mehta ".


AMB

"Miguel Angel Juárez Herrera" wrote:

Saludos amigos.
Pues estoy tratando de cambiar mi forma de programar con cursores.
Tengo un ejemplo que no encuentro como resolverlo, espero alguien me pueda
auxiliar.
El escenario es el siguiente, tengo una tabla con una clave de cliente,
nombres, y total de ventas.
obtengo el valor del total de las ventas y obtengo el total del 80% y del 20%
Los clientes cuyas ventas representen el 80% del total del ingreso son "a" y
los que representan el 20% son "B"
Yo con un cursor ordeno descendentemente por el campo de totalventas, y así
recorro cliente por cliente y voy sumando desde el que mas vende hasta el que
menos y voy poniendoles "A" hasdta completar el 80%, luego la comparación del
ultimo 20 % s eles pone "b"
y mi cursor queda así:

select @total = sum(mesactualacumulado) from Rpt600AB
set @a = @total * .8
set @b = @total * .2
set @total = 0
DECLARE CurAB CURSOR FORWARD_ONLY FOR
select ruta, nud, mesactualacumulado from Rpt600AB order by
mesactualacumulado desc, vtamesAnt1 desc, vtamesAnt2
open CurAB
FETCH NEXT FROM CurAB INTO @ruta, @nud,@mesactualacumulado
WHILE @@FETCH_STATUS = 0
BEGIN
set @total = @total + @mesactualacumulado
if @total <= @a
begin
update Rpt600AB set tipocliente = '80' where nud =
@nud and ruta = @ruta and mesactualacumulado = @mesactualacumulado
end
else
if (@total <= (@a + @b)) and (@total > @a)
begin
update Rpt600AB set tipocliente = '20' where
nud = @nud and ruta = @ruta and mesactualacumulado = @mesactualacumulado
end
FETCH NEXT FROM CurAB INTO @ruta,
@nud,@mesactualacumulado
END
CLOSE CurAB
DEALLOCATE CurAB


existe alguna manera de no hacerlo por cursor?..
Gracias.




Miguel Angel Juárez Herrera.
Programador (NET, VB6 y SQL 2000).
Sistemas GEUSA

Respuesta Responder a este mensaje
#5 Manuel Etcheto
04/07/2007 - 23:20 | Informe spam
Podrías en 2000 hacer una "matraca" con una tabla temporal para no utilizar
cursor, aunque estimo que la aplicación cliente lo podría procesar mas
eficientemente simplemente pasándole las ventas por cliente...

Prueba:

Use Northwind
GO
create table dbo.VentasTotales (
cliente_id int,
totalventas decimal (10,2)
)
GO

insert into dbo.VentasTotales values(1, 10)
insert into dbo.VentasTotales values(2, 10)
insert into dbo.VentasTotales values(3, 20)
insert into dbo.VentasTotales values(4, 5)
insert into dbo.VentasTotales values(6, 5)
insert into dbo.VentasTotales values(7, 12)
insert into dbo.VentasTotales values(8, 8)
insert into dbo.VentasTotales values(9, 10)
insert into dbo.VentasTotales values(10, 3)
insert into dbo.VentasTotales values(11, 3)
insert into dbo.VentasTotales values(12, 2)
insert into dbo.VentasTotales values(13, 2)


CREATE TABLE #t1 (orden int identity (1,1),
cliente_id int, ventas decimal (10,2), acumulado decimal (10,2),
porcentajeAcum decimal (5,2) )

INSERT INTO #T1 (cliente_id, ventas)
SELECT T.cliente_id, T.totalventas
FROM dbo.VentasTotales T
ORDER BY totalventas DESC

UPDATE tem set tem.acumulado = TD.acum
FROM #T1 tem
JOIN
( SELECT T.cliente_id, SUM(TT.ventas) as acum FROM #T1 T
JOIN #T1 TT ON T.orden >= TT.orden
GROUP BY T.cliente_id
) TD
ON Tem.cliente_id = TD.cliente_id

DECLARE @T decimal(10,2)
SET @T = (SELECT SUM(ventas) FROM #T1)
UPDATE #t1 set porcentajeAcum = Cast(((acumulado/ @T) * 100.00 ) as
decimal(5,2))


SELECT * FROM #T1 where orden <= (SELECT MAX(ORDEN) + 1
FROM #T1 where porcentajeAcum < 80 )
SELECT * FROM #T1 where orden > (SELECT MAX(ORDEN) + 1
FROM #T1 where porcentajeAcum < 80 )

select * from #T1 order by orden

DROP TABLE #T1

Aquí en este ejemplo el corte se da en un total de ventas (5.00) repetido,
y 1 queda "afuera" arbitrariamente, seguramente en la realidad este caso no
se dé nunca, pero habría que contemplarlo agregando código...

Suerte
Manuel


"Miguel Angel Juárez Herrera" <mjuarezh36(antispam)@yahoo.com.mx> escribió
en el mensaje news:
Saludos amigos.
Pues estoy tratando de cambiar mi forma de programar con cursores.
Tengo un ejemplo que no encuentro como resolverlo, espero alguien me pueda
auxiliar.
El escenario es el siguiente, tengo una tabla con una clave de cliente,
nombres, y total de ventas.
obtengo el valor del total de las ventas y obtengo el total del 80% y del
20%
Los clientes cuyas ventas representen el 80% del total del ingreso son "a"
y
los que representan el 20% son "B"
Yo con un cursor ordeno descendentemente por el campo de totalventas, y
así
recorro cliente por cliente y voy sumando desde el que mas vende hasta el
que
menos y voy poniendoles "A" hasdta completar el 80%, luego la comparación
del
ultimo 20 % s eles pone "b"
y mi cursor queda así:

select @total = sum(mesactualacumulado) from Rpt600AB
set @a = @total * .8
set @b = @total * .2
set @total = 0
DECLARE CurAB CURSOR FORWARD_ONLY FOR
select ruta, nud, mesactualacumulado from Rpt600AB order by
mesactualacumulado desc, vtamesAnt1 desc, vtamesAnt2
open CurAB
FETCH NEXT FROM CurAB INTO @ruta, @nud,@mesactualacumulado
WHILE @@FETCH_STATUS = 0
BEGIN
set @total = @total + @mesactualacumulado
if @total <= @a
begin
update Rpt600AB set tipocliente = '80' where nud
> @nud and ruta = @ruta and mesactualacumulado = @mesactualacumulado
end
else
if (@total <= (@a + @b)) and (@total > @a)
begin
update Rpt600AB set tipocliente = '20' where
nud = @nud and ruta = @ruta and mesactualacumulado = @mesactualacumulado
end
FETCH NEXT FROM CurAB INTO @ruta,
@nud,@mesactualacumulado
END
CLOSE CurAB
DEALLOCATE CurAB


existe alguna manera de no hacerlo por cursor?..
Gracias.




Miguel Angel Juárez Herrera.
Programador (NET, VB6 y SQL 2000).
Sistemas GEUSA

Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaSiguiente Respuesta Tengo una respuesta
Search Busqueda sugerida