Saludos Maxi
Yo he tenido esa discusión, pero en realidad no solo de cursores, sino de la
mayor parte de la plataforma de desarrollo de Microsoft, ja ja ja, muchas
personas piensan que lo mas basico es lo mejor, y no lo es en el 100% de los
casos, como VS6 vs VS.Net, pero, acerca de SQL principalmente las
discusiones han sido acerca de tablas temporales VS cursores para hacer
scroll en un resultSet, de cualquier forma, aquí va por que considero una
ayuda benigna los cursores, precisamente ayer tuve un detalle acerca de eso,
te muestro el query que estuve trabajando
SELECT
F1.ABAN8 AS ClientID,
CASE
WHEN MIN(PS.FechaActivacion) IS Null THEN 0
ELSE 1
END AS ESelling,
MIN(PS.FechaActivacion) AS ESellingDate,
CASE
WHEN Wap.wapServiceDate IS Null THEN 0
ELSE 1
END AS Wap,
Wap.wapServiceDate AS WapDate,
CASE
WHEN x24Hrs.x24HrsServiceDate IS Null THEN 0
ELSE 1
END AS x24Hrs,
x24Hrs.x24HrsServiceDate AS x24HrsDate,
CASE
WHEN MIN(UGF.StartDate) IS Null THEN 0
ELSE 1
END AS CemPlus,
MIN(UGF.StartDate) AS CemPlusDate,
CASE
WHEN MIN(TCC.RegistrationDate) Is Null THEN 0
ELSE 1
END AS CCases,
MIN(TCC.RegistrationDate) AS CCasesDate,
CASE
WHEN Eficem.EficemDate IS NULL THEN 0 -- Aqui no utilizamos MIN por que
siempre me trae un solo registro
ELSE 1
END AS Eficem,
Eficem.EficemDate AS EficemDate
FROM
F0101 F1
LEFT JOIN EsEsp300.dbo.FProspectos AS PS ON F1.ABAN8 = PS.Cliente --AND
PS.FechaActivacion Is Not Null
LEFT JOIN vw_UsersGF AS UGF ON F1.ABAN8 = UGF.JDECode
LEFT JOIN tCASCases TCC ON F1.ABAN8 = TCC.BranchID
LEFT JOIN (
SELECT
UGF.JDECode AS JDECode,
A.StartDate AS EficemDate
FROM
cpEsp300.dbo.Agreement A
INNER JOIN vw_UsersGF UGF ON A.IDUser = UGF.IDUser
) AS Eficem ON F1.ABAN8 = Eficem.JDECode
LEFT JOIN (
SELECT
T1.SDAN8 AS SDAN8,
CASE WHEN T2.Counter2 IS NULL THEN T1.Counter
ELSE T2.Counter2
END AS x24HrsServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 3
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T1 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2 WHERE
SDUPC1 = 3 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T2 ON T1.SDAN8 T2.SDAN82
) AS x24Hrs ON x24Hrs.SDAN8 = F1.ABAN8
LEFT JOIN (
SELECT
T3.SDAN8 AS SDAN8,
CASE WHEN T4.Counter2 IS NULL THEN T3.Counter
ELSE T4.Counter2
END AS WapServiceDate
FROM
(SELECT SDAN8, MIN(SDTRDJ) AS Counter FROM F4211 F1 WHERE SDUPC1 = 2
AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T3 FULL JOIN
(SELECT SDAN8 AS SDAN82, MIN(SDTRDJ) AS Counter2 FROM F42119 F2 WHERE
SDUPC1 = 2 AND SDTRDJ Is Not Null GROUP BY SDAN8) AS T4 ON T3.SDAN8 T4.SDAN82
) AS Wap ON F1.ABAN8 = Wap.SDAN8
GROUP BY
F1.ABAN8, Wap.wapServiceDate, x24Hrs.x24HrsServiceDate, Eficem.JDECode,
Eficem.EficemDate
HAVING
MIN(PS.FechaActivacion) Is Not Null OR
MIN(Wap.wapServiceDate) Is Not Null OR
MIN(x24Hrs.x24HrsServiceDate) Is Not Null OR
MIN(UGF.StartDate) Is Not Null OR
MIN(TCC.RegistrationDate) Is Not Null
Bueno, como background, la tabla que saca los valores, con DISTINCT (que es
algo asi como la "llave", es con lo que sabemos que registros afectar),
produce 220000+ regs como Result Set, ahora, eso no es problema y SQL los
recupera en menos de 2 secs, el problema viene por que, en la tabla F42119,
consiste de mas de 3 000 000+ regs, filtrandola con la llave, la consula es
instantánea (foreignKey = 'value'), pero en el SELECT no puedo mandarle a un
SELECT anidado el valor explícito de la llave, eso lo tuve que emular con el
JOIN externo (AS Wap ON F1.ABAN8 = Wap.SDAN8), además, las tablas F4211 y
F42119 son identicas, solo que una contiene registros históricos (La de los
3M+) y no puedo utilizar UNION, por que el UNION me producía muchisimos mas
registros y hacía mas pesado el JOIN del nivel superior, y al no poder
enviarle sino atravez del JOIN la llave contra que filtrarlo para cada
registro en particula, me tardaba aún mas.
Como sea, con varias optimizaciones al nivel donde los SELECT metían los
filtrajes, lo mas que pude reducir el tiempo fue a no menos de 5 mins, via
un solo select, mientras que con el cursor corría en mas o menos 4 mins, no
es mucha diferencia, pero teoricamente, el tiempo crecerá exponencialmente
mas para el SELECT que para el CURSOR, por que el cursor manda un valor
especifico a un SP que tiene las colsultas necesarias para generar los
resultados que necesito
En esta ocasión, al menos en las pruebas que hice, el Cursor desempeño de
mejor forma, y el SELECT me afectaba cuando quería correr otro query a
alguna de las tablas, me marcaba timeout, con el Cursor corriendo no, igual
se alentaba el Query, pero respondía, quizá esto ultimo fue coincidencia,
pero fue en mas de una ocasión. E incluso, una de las veces que lo corrí
solo, el mismo parecía como bloquearse en los ultimos registros, y tardó mas
de 20 Min.
Y pues nada mas como respuesta rapida también al respecto, cuando entablo
una discusión sobre cursores, hay cosas que desafortunadamente de otra forma
no puedes realizar, suponiendo por ejemplo, que tuvieras un sistema que
trabajaras con probabilidades, y necesitaras generar números aleatorios para
proyecciones, utilizar RAND en un SELECT pe. SELECT RAND() AS Tendencia,
Field AS Factor FROM TablaHistorico, te va a utilizar el mismo número
aleatorio atravez de todo el Result Set, lo cual, pues sería incorrecto.
Quizá tu nunca has tenido necesidad de utilizarlos en base a los proyectos
que has estado, pero yo sigo pensando que, como la mayoría de las
tecnologías un poco mas complejonas de MS, bien usados, no son un enemigo. Y
decir que su uso es patético, me parece... cierto, pero no siempre.
De cualquier forma, sigo trabajando en ese query, por que me pareció
interesante el hecho de tratar de reducir el tiempo de consulta moviendo de
niveles el filtraje (incluso sacandolo del contexto inicial ^_^) te aviso si
pude hacer que el SELECT jalara aún mas rápido. Suerte
K' Ragnarok
"MAXI" <maxi_da@infovia.com.ar.sacame> wrote in message
news:OLKkXaP0EHA.2804@TK2MSFTNGP15.phx.gbl...
Hola, podrias ampliar un poco en que te basas que los cursores ayudan? yo
considero que son muy malos para tareas de produccion y que se usan porque
es mas facil :(
Te cuento mas, hace unos dias tuve una linda discusion con arquitectos
.net
sobre este tema y demostre que el uso de cursores es patetico para
cualquier
cosa
Maxi
Buenos Aires - Argentina
Desarrollador .NET 3 Estrellas
Microsoft User Group (MUG)
Mail: Maxi_accotto[arroba]speedy.com.ar
Msn Messenger: Maxi_adrogue@msn.com
"K'" <soki.gakiya@adepsa.com.mx> escribió en el mensaje
news:O0xmLPP0EHA.2540@TK2MSFTNGP09.phx.gbl...
> De hecho, si revisas los resultados de tu cursor, hace un fetch linea
por
> linea, como si hicieras un SELECT por renglón
>
> Si creas el SP y lo ejecutas desde QA, debe traerte exactamente el mismo
> resultado (una especie de query multiple), al parecer al no descargar
los
> valores en variables, el CURSOR lo toma como consultas completas
>
> Y supongo que si eso lo estás capturando con ADO, por eso solo te
regresa
> un
> resultset
>
> En realidad no entendí bien cual es tu tirada con ese CURSOR, me parece
> que
> puedes lograr la funcionalidad necesaria sin uso del mismo, los CURSORES
> no
> son malos usados correctamente, te ayudar a agilizar procesos, pero mal
> usados, si representan un riesgo enorme, especialmente en performance,
así
> que mejor dejalos para cuando todo lo demás atenta de forma mas
> comprometedora en tu sistema.
>
> Si nos especificas que necesitas hacer, será mas facil apuntarte en la
dir
> para solucionar tu problema
>
> K'
>
> "Paulino Padial" <paulifoc@telefonica.net> wrote in message
> news:%23X$b4aO0EHA.2688@TK2MSFTNGP09.phx.gbl...
>> Una pregunta, ¿ Te devuelve solo la ultima fila ? , puede ser que
vayan
> por
>> ahi los tiros ;-)
>>
>>
>> "fabicabrera@yahoo.com" <anonymous@discussions.microsoft.com> escribió
en
> el
>> mensaje news:873301c4d0e3$d25fbde0$a601280a@phx.gbl...
>> > Saludos Grupo!
>> >
>> > Necesito crar una consulta como la que sigue
>> > ***********
>> > Use Pubs
>> > Go
>> > DECLARE authors_cursor CURSOR
>> > FOR SELECT * FROM authors
>> > OPEN authors_cursor
>> >
>> > FETCH NEXT FROM authors_cursor
>> > WHILE @@FETCH_STATUS = 0
>> > BEGIN
>> > FETCH NEXT FROM authors_cursor
>> > END
>> > CLOSE authors_cursor
>> > DEALLOCATE authors_cursor
>> > ****
>> >
>> > Cuando lo ejecuto en el analizador de consultas de SQL
>> > funciona perfectamente, pero cuando lo guardo en un
>> > procedimieto almacenado y lo llamo desde mi aplicacion me
>> > retorna solo la primera fila...
>> >
>> > Si alguien puede ayudarme, gracias de Antemano
>> >
>> > Fabi
>>
>>
>
>
Leer las respuestas