T-SQL / cursores

30/10/2003 - 13:06 por cdiaz | Informe spam
Dado que observo que las T-SQL son mucho más rápidas que los cursoses me
gustaría saber si el siguiente caso tendría una buena solución con T-SQL.
(ahora lo tengo hecho como un procedimiento secuencial)

Datos "reales"
<< Tabla1 >>
Código Fecha Obra
1 01-12-2002 Obra1
2 05-07-2002 Obra2
4 vacío vacío

<< Tabla 2 >>
Código Fecha Obra
1 05-01-2003 Obra4
1 10-01-2003 Obra1
4 05-01-2003 Obra1

El significado de estos datos es:

El código 1 entró en la obra1 el 01-12-2002 y salió el 05-01-2003
El código 1 entró en la obra4 el 05-01-2003 y salió el 10-01-2003
El código 1 entró en la obra1 el 10-01-2003 y todavía está en dicha obra1
El código 2 está en la obra2 desde el 05-07-2002. Está todavía en la obra2.
El código 4 ha aparecido en la obra1 el día 05-01-2003

El objetivo de la T-SQL es obtener los días que ha estado cada uno de los
códigos en cada una de las obras desde una fecha determinada. Cuántos días
hay que facturar a cada una de las obras.

La última fecha de facturación fue el 31-12-2002 y la nueva fecha es el
31-01-2003. Los resultados de facturación que se desean obtener son.

Código Obra Desde
Hasta Días
1 Obra1 01-01-2003 (Fecha de la última
facturación +1) 05-01-2003
5
1 Obra1 10-01-2003
31-01-2003 (Fecha de la facturación actual) 20
1 Obra4 05-01-2003
10-01-2003 4
2 Obra2 01-01-2003 (Fecha de la última
facturación +1) 31-01-2003 (Fecha de la facturación actual)
31
4 Obra1 05-01-2003
31-01-2003 (Fecha de la facturación actual) 26

Gracias de antemano

Preguntas similare

Leer las respuestas

#6 cdiaz
03/11/2003 - 13:02 | Informe spam
FUNCIONA. La parte de facturación la he hecho de la siguiente manera tomando
las ideas de Liliana.

DECLARE @desde datetime, @hasta datetime
SELECT @desde = '20030101', @hasta = '20030131'

SELECT Codigo, Obra
FecEntrada CASE
WHEN FechaEntradaObra < @desde THEN @desde
ELSE FechaEntradaObra
END,
FecSalida CASE
WHEN FechaSalidaObra > @hasta THEN @hasta
WHEN FechaSalidaObra is null then @hasta
ELSE FechaSalidaObra
END,
datediff (dd,
CASE
WHEN FechaEntradaObra < @desde THEN @desde
ELSE FechaEntradaObra
END,
CASE
WHEN FechaSalidaObra > @hasta THEN @hasta
WHEN FechaSalidaObra is null then @hasta
ELSE FechaSalidaObra
END
)
FROM EntradasySalidasMaquinaria
ORDER BY Codigo, FecEntrada

La verdad es que en un primer momento esperaba que funcionara datediff ( dd,
FecEntrada, FecSalida) pero si pongo esto salta el mensaje "El nombre de
columna 'FecEntrada' no es válido." (lo mismo para FecSalida).

He optado por tu opción porque, aunque la de Liliana la entendía, cuando
vuelva a repasar/retocar el código me costaría mucho volverla a entender.

Gracias y enhorabuena por una solución tan buena y tan rápida. Intentaré
hacer el esfuerzo de antes de usar un cursor, hacerlo con un T-SQL. La
actitud la tengo pero TODAVÍA no he conseguido la aptitud.

Un saludo

"Javier Loria" escribió en el mensaje
news:
Hola Carlos:
Me alegro mucho, que estas pensando de estas forma, si no te importa


lo
podemos hacer por partes para que no salgas corriendo, porque si leiste el
codigo de Lililiana sabras que no es facil escribirlo y requiere un


"cambio
mental".
No se si estas de acuerdo al decir que si tuvieramos una Tabla con las
columnas: Codigo, Obra1, FechaEntradaObra y FechaSalidaObra, seria MUCHO


mas
facil el codigo de Facturacion. Si estas de acuerdo la "construimos" a
traves de una vista, para no hacer el codigo ilegible.
Basado en el siguiente codigo de creacion de tablas:

/* Codigo de Creacion de Tablas */
/* e Insercion de Filas de Pruebas */
CREATE TABLE Tabla1(
Codigo INT NOT NULL PRIMARY KEY,
Fecha SMALLDATETIME NULL,
Obra VARCHAR(8) NULL,
)

CREATE TABLE Tabla2(
Codigo INT NOT NULL,
Fecha SMALLDATETIME NOT NULL,
Obra VARCHAR(8) NOT NULL
CONSTRAINT PK_TABLA2 PRIMARY KEY(Codigo, Fecha)
)

SET DATEFORMAT dmy
INSERT Tabla1(Codigo, Fecha,Obra)
SELECT 1, '01-12-2002','Obra1' UNION ALL
SELECT 2, '05-07-2002','Obra2' UNION ALL
SELECT 4, NULL, NULL

INSERT Tabla2(Codigo, Fecha,Obra)
SELECT 1,'05-01-2003','Obra4' UNION ALL
SELECT 1,'10-01-2003','Obra1' UNION ALL
SELECT 4,'05-01-2003','Obra1'
/* Fin de Creacion de Tablas */

Veras que asumo que algunas llaves primarias, espero que esten correctas
sino el codigo que sigue no funcionaria.

Debido a la fuente de los datos podemos partir en tres el conjunto de
datos, y asumiendo que la tabla1 es la de Compras de Equipo o algo como


eso
podriamos poner:
Maquinaria que se Compro y Entro Directamente a la Obra.
Maquinaria que se Movio entre Obras.
Maquinaria que esta Actualmente en la obra.
Si es asi los siguientes SELECT unidos nos dan el cojunto total de


periodos
en que ha estado la maquinara en la obra.
/* Creacion de Vista de Movimientos Maquinaria */
CREATE View EntradasySalidasMaquinaria
AS
SELECT Tabla1.Codigo,
Tabla1.Obra,
Tabla1.Fecha AS FechaEntradaObra,
T2.Fecha AS FechaSalidaObra
FROM Tabla1 LEFT JOIN
(SELECT Codigo, MIN(Fecha) AS Fecha
FROM Tabla2
GROUP BY Codigo) AS T2
ON Tabla1.Codigo=T2.Codigo
WHERE Tabla1.Obra IS NOT NULL
UNION ALL
SELECT T1.Codigo,
T1.Obra,
T1.Fecha AS FechaEntradaObra,
MIN(T2.Fecha) AS FechaSalidaObra
FROM Tabla2 AS T1
JOIN Tabla2 AS T2
ON T1.Codigo=T2.Codigo AND
T1.Fecha<T2.Fecha
GROUP BY T1.Codigo, T1.Obra, T1.Fecha
UNION ALL
Maquinaria que esta Actualmente en la obra.
SELECT T1.Codigo,
T1.Obra,
T1.Fecha AS FechaEntradaObra,
NULL AS FechaSalidaObra
FROM Tabla2 AS T1
JOIN
(SELECT Codigo,
MAX(Fecha) as FECHA
FROM Tabla2
GROUP BY Codigo) AS T2
ON
T1.Codigo=T2.Codigo AND
T1.Fecha=T2.Fecha
/* Fin de Vista */
Revisa la vista, haber si es correcta la logica que estoy aplicando y si


lo
es continuamos con la parte de Facturacion.

Saludos,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.




cdiaz escribio:
> Cuando hablo de cursores hago referencia a SQL. Yo tiendo a utilizar
> el típico algoritmo de recorrer hasta fin de fichero e ir procesando
> registro a registro. Pues bien, leyendo mensajes de este grupo
> (últimamente de Liliana Sorrentino) hay muchas soluciones hechas con
> T-SQL que yo hubiera hecho con un cursor. Si comparo los tiempos de
> respuesta entre el cursor y la T-SQL , ésta última es mucho más
> rápida.
>
> Respecto a mi problema, se usan 2 tablas porque éstas proceden de un
> sistema migrado de otras bases de datos. La Tabla1 serían los datos
> maestros de los códigos y la Tabla2 serían los datos de los
> movimientos del mes de dichos códigos. La Tabla1 contiene la fecha y
> la obra de la situación a principio de mes del código. Existe también
> en este sistema migrado un histórico de movimientos con los registros
> así:
>
> Código Fecha Obra
> 1 01-12-2002 Obra1
> 1 05-01-2003 Obra4
> 1 10-01-2003 Obra1
> 2 05-07-2002 Obra2
> 4 05-01-2003 Obra1
>
> Se lanza el proceso de facturación y el resultado se desea que sea
> como el comentado en los anteriores mensajes. Si se puede obtener el
> mismo resultado leyendo de este histórico serviría también. Hay que
> tener en cuenta que en este histórico existen muchos registros pues
> son los datos de los movimientos desde el año 96.
>
> Gracias
>
>
> "Accotto Maximiliano Damian" escribió en
> el mensaje news:uIIr%
>> Hola!! 2 temas
>>
>> 1) vos cuando hablas de cursores hablas de SQL o de programacion
>> como vb?
>>
>> Yo aconsejo no usar T-sql para programar ya que no es un lenguaje de
>> programacion como VB,c# o alguno de ellos.
>> Por mas que T-SQL nos permita hacer triggers y store, estos si se
>> empiezan a complicar no es aconsejable usar T-SQL (por lo que lei en
>> nuevas versiones de SQL tendra incorporado .Net).
>>
>> Bien pasando a tu problema porque no me explicas porque usas 2
>> tablas y mejor aun el analisis del sistema, asi entiendo si el
>> aplicar esas 2 tablas de esa forma es correcto o hay una forma mas
>> optima de hacer la misma tarea.
>>
>> Un abrazo
>>
>> Accotto Maximiliano Damian
>> "cdiaz" escribió en el mensaje
>> news:
>>> Dado que observo que las T-SQL son mucho más rápidas que los
>>> cursoses me gustaría saber si el siguiente caso tendría una buena
>>> solución con T-SQL. (ahora lo tengo hecho como un procedimiento
>>> secuencial)
>>>
>>> Datos "reales"
>>> << Tabla1 >>
>>> Código Fecha Obra
>>> 1 01-12-2002 Obra1
>>> 2 05-07-2002 Obra2
>>> 4 vacío vacío
>>>
>>> << Tabla 2 >>
>>> Código Fecha Obra
>>> 1 05-01-2003 Obra4
>>> 1 10-01-2003 Obra1
>>> 4 05-01-2003 Obra1
>>>
>>> El significado de estos datos es:
>>>
>>> El código 1 entró en la obra1 el 01-12-2002 y salió el 05-01-2003
>>> El código 1 entró en la obra4 el 05-01-2003 y salió el 10-01-2003
>>> El código 1 entró en la obra1 el 10-01-2003 y todavía está en
>>> dicha obra1 El código 2 está en la obra2 desde el 05-07-2002. Está
>>> todavía en la obra2. El código 4 ha aparecido en la obra1 el día
>>> 05-01-2003
>>>
>>> El objetivo de la T-SQL es obtener los días que ha estado cada uno
>>> de los códigos en cada una de las obras desde una fecha
>>> determinada. Cuántos días hay que facturar a cada una de las obras.
>>>
>>> La última fecha de facturación fue el 31-12-2002 y la nueva fecha
>>> es el 31-01-2003. Los resultados de facturación que se desean
>>> obtener son.
>>>
>>> Código Obra Desde
>>> Hasta
>>> Días 1 Obra1 01-01-2003 (Fecha de la
>>> última facturación +1) 05-01-2003
>>> 5
>>> 1 Obra1 10-01-2003
>>> 31-01-2003 (Fecha de la facturación actual) 20
>>> 1 Obra4 05-01-2003
>>> 10-01-2003 4
>>> 2 Obra2 01-01-2003 (Fecha de la
>>> última facturación +1) 31-01-2003 (Fecha de la
>>> facturación actual) 31
>>> 4 Obra1 05-01-2003
>>> 31-01-2003 (Fecha de la facturación actual) 26
>>>
>>> Gracias de antemano


Respuesta Responder a este mensaje
#7 Javier Loria
04/11/2003 - 05:44 | Informe spam
Hola Carlos:
Manejaste muy bien los CASE.
El CASE es probablmente la mejor herramienta que tienes para eliminar
los CURSORES.
Felicitaciones,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.
cdiaz escribio:
FUNCIONA. La parte de facturación la he hecho de la siguiente manera
tomando las ideas de Liliana.

DECLARE @desde datetime, @hasta datetime
SELECT @desde = '20030101', @hasta = '20030131'

SELECT Codigo, Obra
FecEntrada > CASE
WHEN FechaEntradaObra < @desde THEN @desde
ELSE FechaEntradaObra
END,
FecSalida > CASE
WHEN FechaSalidaObra > @hasta THEN @hasta
WHEN FechaSalidaObra is null then @hasta
ELSE FechaSalidaObra
END,
datediff (dd,
CASE
WHEN FechaEntradaObra < @desde THEN @desde
ELSE FechaEntradaObra
END,
CASE
WHEN FechaSalidaObra > @hasta THEN @hasta
WHEN FechaSalidaObra is null then @hasta
ELSE FechaSalidaObra
END
)
FROM EntradasySalidasMaquinaria
ORDER BY Codigo, FecEntrada

La verdad es que en un primer momento esperaba que funcionara
datediff ( dd, FecEntrada, FecSalida) pero si pongo esto salta el
mensaje "El nombre de columna 'FecEntrada' no es válido." (lo mismo
para FecSalida).

He optado por tu opción porque, aunque la de Liliana la entendía,
cuando vuelva a repasar/retocar el código me costaría mucho volverla
a entender.

Gracias y enhorabuena por una solución tan buena y tan rápida.
Intentaré hacer el esfuerzo de antes de usar un cursor, hacerlo con
un T-SQL. La actitud la tengo pero TODAVÍA no he conseguido la
aptitud.

Un saludo

"Javier Loria" escribió en el mensaje
news:
Hola Carlos:
Me alegro mucho, que estas pensando de estas forma, si no te
importa lo podemos hacer por partes para que no salgas corriendo,
porque si leiste el codigo de Lililiana sabras que no es facil
escribirlo y requiere un "cambio mental".
No se si estas de acuerdo al decir que si tuvieramos una Tabla
con las columnas: Codigo, Obra1, FechaEntradaObra y FechaSalidaObra,
seria MUCHO mas facil el codigo de Facturacion. Si estas de acuerdo
la "construimos" a traves de una vista, para no hacer el codigo
ilegible.
Basado en el siguiente codigo de creacion de tablas:

/* Codigo de Creacion de Tablas */
/* e Insercion de Filas de Pruebas */
CREATE TABLE Tabla1(
Codigo INT NOT NULL PRIMARY KEY,
Fecha SMALLDATETIME NULL,
Obra VARCHAR(8) NULL,
)

CREATE TABLE Tabla2(
Codigo INT NOT NULL,
Fecha SMALLDATETIME NOT NULL,
Obra VARCHAR(8) NOT NULL
CONSTRAINT PK_TABLA2 PRIMARY KEY(Codigo, Fecha)
)

SET DATEFORMAT dmy
INSERT Tabla1(Codigo, Fecha,Obra)
SELECT 1, '01-12-2002','Obra1' UNION ALL
SELECT 2, '05-07-2002','Obra2' UNION ALL
SELECT 4, NULL, NULL

INSERT Tabla2(Codigo, Fecha,Obra)
SELECT 1,'05-01-2003','Obra4' UNION ALL
SELECT 1,'10-01-2003','Obra1' UNION ALL
SELECT 4,'05-01-2003','Obra1'
/* Fin de Creacion de Tablas */

Veras que asumo que algunas llaves primarias, espero que esten
correctas sino el codigo que sigue no funcionaria.

Debido a la fuente de los datos podemos partir en tres el
conjunto de datos, y asumiendo que la tabla1 es la de Compras de
Equipo o algo como eso podriamos poner:
Maquinaria que se Compro y Entro Directamente a la Obra.
Maquinaria que se Movio entre Obras.
Maquinaria que esta Actualmente en la obra.
Si es asi los siguientes SELECT unidos nos dan el cojunto total de
periodos en que ha estado la maquinara en la obra.
/* Creacion de Vista de Movimientos Maquinaria */
CREATE View EntradasySalidasMaquinaria
AS
SELECT Tabla1.Codigo,
Tabla1.Obra,
Tabla1.Fecha AS FechaEntradaObra,
T2.Fecha AS FechaSalidaObra
FROM Tabla1 LEFT JOIN
(SELECT Codigo, MIN(Fecha) AS Fecha
FROM Tabla2
GROUP BY Codigo) AS T2
ON Tabla1.Codigo=T2.Codigo
WHERE Tabla1.Obra IS NOT NULL
UNION ALL
SELECT T1.Codigo,
T1.Obra,
T1.Fecha AS FechaEntradaObra,
MIN(T2.Fecha) AS FechaSalidaObra
FROM Tabla2 AS T1
JOIN Tabla2 AS T2
ON T1.Codigo=T2.Codigo AND
T1.Fecha<T2.Fecha
GROUP BY T1.Codigo, T1.Obra, T1.Fecha
UNION ALL
Maquinaria que esta Actualmente en la obra.
SELECT T1.Codigo,
T1.Obra,
T1.Fecha AS FechaEntradaObra,
NULL AS FechaSalidaObra
FROM Tabla2 AS T1
JOIN
(SELECT Codigo,
MAX(Fecha) as FECHA
FROM Tabla2
GROUP BY Codigo) AS T2
ON
T1.Codigo=T2.Codigo AND
T1.Fecha=T2.Fecha
/* Fin de Vista */
Revisa la vista, haber si es correcta la logica que estoy aplicando
y si lo es continuamos con la parte de Facturacion.

Saludos,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.




cdiaz escribio:
Cuando hablo de cursores hago referencia a SQL. Yo tiendo a utilizar
el típico algoritmo de recorrer hasta fin de fichero e ir procesando
registro a registro. Pues bien, leyendo mensajes de este grupo
(últimamente de Liliana Sorrentino) hay muchas soluciones hechas con
T-SQL que yo hubiera hecho con un cursor. Si comparo los tiempos de
respuesta entre el cursor y la T-SQL , ésta última es mucho más
rápida.

Respecto a mi problema, se usan 2 tablas porque éstas proceden de un
sistema migrado de otras bases de datos. La Tabla1 serían los datos
maestros de los códigos y la Tabla2 serían los datos de los
movimientos del mes de dichos códigos. La Tabla1 contiene la fecha y
la obra de la situación a principio de mes del código. Existe
también en este sistema migrado un histórico de movimientos con los
registros así:

Código Fecha Obra
1 01-12-2002 Obra1
1 05-01-2003 Obra4
1 10-01-2003 Obra1
2 05-07-2002 Obra2
4 05-01-2003 Obra1

Se lanza el proceso de facturación y el resultado se desea que sea
como el comentado en los anteriores mensajes. Si se puede obtener el
mismo resultado leyendo de este histórico serviría también. Hay que
tener en cuenta que en este histórico existen muchos registros pues
son los datos de los movimientos desde el año 96.

Gracias


"Accotto Maximiliano Damian" escribió
en el mensaje news:uIIr%
Hola!! 2 temas

1) vos cuando hablas de cursores hablas de SQL o de programacion
como vb?

Yo aconsejo no usar T-sql para programar ya que no es un lenguaje
de programacion como VB,c# o alguno de ellos.
Por mas que T-SQL nos permita hacer triggers y store, estos si se
empiezan a complicar no es aconsejable usar T-SQL (por lo que lei
en nuevas versiones de SQL tendra incorporado .Net).

Bien pasando a tu problema porque no me explicas porque usas 2
tablas y mejor aun el analisis del sistema, asi entiendo si el
aplicar esas 2 tablas de esa forma es correcto o hay una forma mas
optima de hacer la misma tarea.

Un abrazo

Accotto Maximiliano Damian
"cdiaz" escribió en el mensaje
news:
Dado que observo que las T-SQL son mucho más rápidas que los
cursoses me gustaría saber si el siguiente caso tendría una buena
solución con T-SQL. (ahora lo tengo hecho como un procedimiento
secuencial)

Datos "reales"
<< Tabla1 >>
Código Fecha Obra
1 01-12-2002 Obra1
2 05-07-2002 Obra2
4 vacío vacío

<< Tabla 2 >>
Código Fecha Obra
1 05-01-2003 Obra4
1 10-01-2003 Obra1
4 05-01-2003 Obra1

El significado de estos datos es:

El código 1 entró en la obra1 el 01-12-2002 y salió el 05-01-2003
El código 1 entró en la obra4 el 05-01-2003 y salió el 10-01-2003
El código 1 entró en la obra1 el 10-01-2003 y todavía está en
dicha obra1 El código 2 está en la obra2 desde el 05-07-2002.
Está todavía en la obra2. El código 4 ha aparecido en la obra1
el día 05-01-2003

El objetivo de la T-SQL es obtener los días que ha estado cada uno
de los códigos en cada una de las obras desde una fecha
determinada. Cuántos días hay que facturar a cada una de las
obras.

La última fecha de facturación fue el 31-12-2002 y la nueva fecha
es el 31-01-2003. Los resultados de facturación que se desean
obtener son.

Código Obra Desde
Hasta
Días 1 Obra1 01-01-2003 (Fecha de
la última facturación +1) 05-01-2003
5
1 Obra1 10-01-2003
31-01-2003 (Fecha de la facturación actual) 20
1 Obra4 05-01-2003
10-01-2003 4
2 Obra2 01-01-2003 (Fecha de la
última facturación +1) 31-01-2003 (Fecha de la
facturación actual) 31
4 Obra1 05-01-2003
31-01-2003 (Fecha de la facturación actual) 26

Gracias de antemano
Respuesta Responder a este mensaje
#8 Jose Antonio
04/11/2003 - 14:05 | Informe spam
Da la impresión por vuestros comentarios, que nunca hay que usar cursores.
Estoy de acuerdo que hay que intentar evitarlos, pero hay situaciones como
en los triggers con inserciones, actualizaciones y borrados multiples donde
son imprescindibles.

Saludos.
Jose Antonio
"Miguel Egea" escribió en el mensaje
news:
¡Así me gusta Liliana! Creando adeptos.

=> Miguel Egea
http://www.portalsql.com
Microsoft SQL-SERVER MVP.
Brigada Anti-Cursores
Aviso de Seguridad



http://www.microsoft.com/spain/tech...9-USER.asp
==>
"Liliana Sorrentino" escribió en el


mensaje
news:
> Hola,
> ¡Uno más para la brigada anti-cursores!
> Esto no es de lo mejor en plan de ejecución, pero depende también de la
> cantidad de información que manejes. Igual sigo trabajando a ver si


puedo
> mejorarlo.
> Acabo de ver la propuesta de Javier, tendrás que ver los tiempos en
función
> de la cantidad de datos.
> Saludos... Liliana.
>
> DECLARE @desde datetime, @hasta datetime
> SELECT @desde = '20030101', @hasta = '20030131'
> SELECT t1.codigo, t1.obra,
> CONVERT(CHAR(10), case when t1.fecha < @desde THEN @desde ELSE t1.fecha
> END, 112),
> CONVERT(CHAR(10), ISNULL((select min(fecha) from #tabla2 where


t1.codigo
> > codigo AND t1.fecha < fecha), @hasta), 112),
> DATEDIFF(dd, CASE WHEN t1.fecha < @desde THEN @desde ELSE t1.fecha END,
> ISNULL((SELECT MIN(fecha) FROM #tabla2 WHERE t1.codigo = codigo


AND
> t1.fecha < fecha), @hasta))
> FROM #tabla1 t1
> WHERE t1.fecha is not null
> UNION
> SELECT t2.codigo, t2.obra,
> CONVERT(CHAR(10), t2.fecha, 112),
> CONVERT(CHAR(10),
> ISNULL( (SELECT MIN(fecha) FROM #tabla1 WHERE t2.codigo = codigo
> and t2.fecha < fecha),
> ISNULL( (SELECT MIN(fecha) FROM #tabla2 t22 WHERE t2.codigo t22.codigo
> and t2.fecha < t22.fecha), @hasta)), 112),
> DATEDIFF(dd, t2.fecha,
> ISNULL( (SELECT MIN(fecha) FROM #tabla1 WHERE t2.codigo = codigo
> and t2.fecha < fecha),
> ISNULL( (SELECT MIN(fecha) FROM #tabla2 t22 WHERE t2.codigo t22.codigo
> and t2.fecha < t22.fecha), @hasta)))
> FROM #tabla2 t2
> ORDER BY 2, 3, 4, 5
>
> "cdiaz" escribió en el mensaje
> news:#
> > Cuando hablo de cursores hago referencia a SQL. Yo tiendo a utilizar


el
> > típico algoritmo de recorrer hasta fin de fichero e ir procesando
registro
> a
> > registro. Pues bien, leyendo mensajes de este grupo (últimamente de
> Liliana
> > Sorrentino) hay muchas soluciones hechas con T-SQL que yo hubiera


hecho
> con
> > un cursor. Si comparo los tiempos de respuesta entre el cursor y la
T-SQL
> ,
> > ésta última es mucho más rápida.
> >
> > Respecto a mi problema, se usan 2 tablas porque éstas proceden de un
> sistema
> > migrado de otras bases de datos. La Tabla1 serían los datos maestros


de
> los
> > códigos y la Tabla2 serían los datos de los movimientos del mes de
dichos
> > códigos. La Tabla1 contiene la fecha y la obra de la situación a
principio
> > de mes del código. Existe también en este sistema migrado un histórico
de
> > movimientos con los registros así:
> >
> > Código Fecha Obra
> > 1 01-12-2002 Obra1
> > 1 05-01-2003 Obra4
> > 1 10-01-2003 Obra1
> > 2 05-07-2002 Obra2
> > 4 05-01-2003 Obra1
> >
> > Se lanza el proceso de facturación y el resultado se desea que sea


como
el
> > comentado en los anteriores mensajes. Si se puede obtener el mismo
> resultado
> > leyendo de este histórico serviría también. Hay que tener en cuenta


que
en
> > este histórico existen muchos registros pues son los datos de los
> > movimientos desde el año 96.
> >
> > Gracias
> >
> >
> > "Accotto Maximiliano Damian" escribió en


el
> > mensaje news:uIIr%
> > > Hola!! 2 temas
> > >
> > > 1) vos cuando hablas de cursores hablas de SQL o de programacion


como
> vb?
> > >
> > > Yo aconsejo no usar T-sql para programar ya que no es un lenguaje de
> > > programacion como VB,c# o alguno de ellos.
> > > Por mas que T-SQL nos permita hacer triggers y store, estos si se
> empiezan
> > a
> > > complicar no es aconsejable usar T-SQL (por lo que lei en nuevas
> versiones
> > > de SQL tendra incorporado .Net).
> > >
> > > Bien pasando a tu problema porque no me explicas porque usas 2


tablas
y
> > > mejor aun el analisis del sistema, asi entiendo si el aplicar esas 2
> > tablas
> > > de esa forma es correcto o hay una forma mas optima de hacer la


misma
> > tarea.
> > >
> > > Un abrazo
> > >
> > > Accotto Maximiliano Damian
> > > "cdiaz" escribió en el mensaje
> > > news:
> > > > Dado que observo que las T-SQL son mucho más rápidas que los
cursoses
> me
> > > > gustaría saber si el siguiente caso tendría una buena solución con
> > T-SQL.
> > > > (ahora lo tengo hecho como un procedimiento secuencial)
> > > >
> > > > Datos "reales"
> > > > << Tabla1 >>
> > > > Código Fecha Obra
> > > > 1 01-12-2002 Obra1
> > > > 2 05-07-2002 Obra2
> > > > 4 vacío vacío
> > > >
> > > > << Tabla 2 >>
> > > > Código Fecha Obra
> > > > 1 05-01-2003 Obra4
> > > > 1 10-01-2003 Obra1
> > > > 4 05-01-2003 Obra1
> > > >
> > > > El significado de estos datos es:
> > > >
> > > > El código 1 entró en la obra1 el 01-12-2002 y salió el 05-01-2003
> > > > El código 1 entró en la obra4 el 05-01-2003 y salió el 10-01-2003
> > > > El código 1 entró en la obra1 el 10-01-2003 y todavía está en


dicha
> > obra1
> > > > El código 2 está en la obra2 desde el 05-07-2002. Está todavía en
la
> > > obra2.
> > > > El código 4 ha aparecido en la obra1 el día 05-01-2003
> > > >
> > > > El objetivo de la T-SQL es obtener los días que ha estado cada uno
de
> > los
> > > > códigos en cada una de las obras desde una fecha determinada.
Cuántos
> > días
> > > > hay que facturar a cada una de las obras.
> > > >
> > > > La última fecha de facturación fue el 31-12-2002 y la nueva fecha


es
> el
> > > > 31-01-2003. Los resultados de facturación que se desean obtener


son.
> > > >
> > > > Código Obra Desde
> > > > Hasta
> Días
> > > > 1 Obra1 01-01-2003 (Fecha de la
última
> > > > facturación +1) 05-01-2003
> > > > 5
> > > > 1 Obra1 10-01-2003
> > > > 31-01-2003 (Fecha de la facturación actual) 20
> > > > 1 Obra4 05-01-2003
> > > > 10-01-2003 4
> > > > 2 Obra2 01-01-2003 (Fecha de la
última
> > > > facturación +1) 31-01-2003 (Fecha de la


facturación
> > > actual)
> > > > 31
> > > > 4 Obra1 05-01-2003
> > > > 31-01-2003 (Fecha de la facturación actual) 26
> > > >
> > > > Gracias de antemano
> > > >
> > > >
> > >
> > >
> >
> >
>
>


Respuesta Responder a este mensaje
#9 Javier Loria
04/11/2003 - 14:47 | Informe spam
Hola Jose Antonio:
Mas que nada en un trigger NO deberias usar cursores. La razon es que el
codigo del trigger "atraza" la transaccion, aumenta los bloqueos y en
general mata el rendimiento del servidor.
Efectivamente en los triggers las inserciones/actualizaciones y borrados
son multiples, pero precisamente la fuerza de SQL esta en este tipo de
codigo.
Si nos mandas un ejemplo podemos trabajar con algo de codigo.
Saludos,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.

Jose Antonio escribio:
Da la impresión por vuestros comentarios, que nunca hay que usar
cursores. Estoy de acuerdo que hay que intentar evitarlos, pero hay
situaciones como en los triggers con inserciones, actualizaciones y
borrados multiples donde son imprescindibles.

Saludos.
Jose Antonio
"Miguel Egea" escribió en el mensaje
news:
¡Así me gusta Liliana! Creando adeptos.

=>> Miguel Egea
http://www.portalsql.com
Microsoft SQL-SERVER MVP.
Brigada Anti-Cursores
Aviso de Seguridad






http://www.microsoft.com/spain/tech...9-USER.asp
==>>
"Liliana Sorrentino" escribió en el
mensaje news:
Hola,
¡Uno más para la brigada anti-cursores!
Esto no es de lo mejor en plan de ejecución, pero depende también
de la cantidad de información que manejes. Igual sigo trabajando a
ver si puedo mejorarlo.
Acabo de ver la propuesta de Javier, tendrás que ver los tiempos en
función de la cantidad de datos.
Saludos... Liliana.

DECLARE @desde datetime, @hasta datetime
SELECT @desde = '20030101', @hasta = '20030131'
SELECT t1.codigo, t1.obra,
CONVERT(CHAR(10), case when t1.fecha < @desde THEN @desde ELSE
t1.fecha END, 112),
CONVERT(CHAR(10), ISNULL((select min(fecha) from #tabla2 where
t1.codigo = codigo AND t1.fecha < fecha), @hasta), 112),
DATEDIFF(dd, CASE WHEN t1.fecha < @desde THEN @desde ELSE t1.fecha
END, ISNULL((SELECT MIN(fecha) FROM #tabla2 WHERE t1.codigo
= codigo AND t1.fecha < fecha), @hasta))
FROM #tabla1 t1
WHERE t1.fecha is not null
UNION
SELECT t2.codigo, t2.obra,
CONVERT(CHAR(10), t2.fecha, 112),
CONVERT(CHAR(10),
ISNULL( (SELECT MIN(fecha) FROM #tabla1 WHERE t2.codigo >>> codigo and t2.fecha < fecha),
ISNULL( (SELECT MIN(fecha) FROM #tabla2 t22 WHERE t2.codigo >>> t22.codigo and t2.fecha < t22.fecha), @hasta)), 112),
DATEDIFF(dd, t2.fecha,
ISNULL( (SELECT MIN(fecha) FROM #tabla1 WHERE t2.codigo >>> codigo and t2.fecha < fecha),
ISNULL( (SELECT MIN(fecha) FROM #tabla2 t22 WHERE t2.codigo >>> t22.codigo and t2.fecha < t22.fecha), @hasta)))
FROM #tabla2 t2
ORDER BY 2, 3, 4, 5

"cdiaz" escribió en el mensaje
news:#
Cuando hablo de cursores hago referencia a SQL. Yo tiendo a
utilizar el típico algoritmo de recorrer hasta fin de fichero e ir
procesando registro a registro. Pues bien, leyendo mensajes de
este grupo (últimamente de Liliana Sorrentino) hay muchas
soluciones hechas con T-SQL que yo hubiera hecho con un cursor. Si
comparo los tiempos de respuesta entre el cursor y la T-SQL , ésta
última es mucho más rápida.

Respecto a mi problema, se usan 2 tablas porque éstas proceden de
un sistema migrado de otras bases de datos. La Tabla1 serían los
datos maestros de los códigos y la Tabla2 serían los datos de los
movimientos del mes de dichos códigos. La Tabla1 contiene la fecha
y la obra de la situación a principio de mes del código. Existe
también en este sistema migrado un histórico de movimientos con
los registros así:

Código Fecha Obra
1 01-12-2002 Obra1
1 05-01-2003 Obra4
1 10-01-2003 Obra1
2 05-07-2002 Obra2
4 05-01-2003 Obra1

Se lanza el proceso de facturación y el resultado se desea que sea
como el comentado en los anteriores mensajes. Si se puede obtener
el mismo resultado leyendo de este histórico serviría también. Hay
que tener en cuenta que en este histórico existen muchos registros
pues son los datos de los movimientos desde el año 96.

Gracias


"Accotto Maximiliano Damian" escribió
en el mensaje news:uIIr%
Hola!! 2 temas

1) vos cuando hablas de cursores hablas de SQL o de programacion
como vb?

Yo aconsejo no usar T-sql para programar ya que no es un lenguaje
de programacion como VB,c# o alguno de ellos.
Por mas que T-SQL nos permita hacer triggers y store, estos si se
empiezan a complicar no es aconsejable usar T-SQL (por lo que lei
en nuevas versiones de SQL tendra incorporado .Net).

Bien pasando a tu problema porque no me explicas porque usas 2
tablas y mejor aun el analisis del sistema, asi entiendo si el
aplicar esas 2 tablas de esa forma es correcto o hay una forma
mas optima de hacer la misma tarea.

Un abrazo

Accotto Maximiliano Damian
"cdiaz" escribió en el mensaje
news:
Dado que observo que las T-SQL son mucho más rápidas que los
cursoses me gustaría saber si el siguiente caso tendría una
buena solución con T-SQL. (ahora lo tengo hecho como un
procedimiento secuencial)

Datos "reales"
<< Tabla1 >>
Código Fecha Obra
1 01-12-2002 Obra1
2 05-07-2002 Obra2
4 vacío vacío

<< Tabla 2 >>
Código Fecha Obra
1 05-01-2003 Obra4
1 10-01-2003 Obra1
4 05-01-2003 Obra1

El significado de estos datos es:

El código 1 entró en la obra1 el 01-12-2002 y salió el
05-01-2003 El código 1 entró en la obra4 el 05-01-2003 y salió
el 10-01-2003 El código 1 entró en la obra1 el 10-01-2003 y
todavía está en dicha obra1 El código 2 está en la obra2 desde
el 05-07-2002. Está todavía en la obra2. El código 4 ha
aparecido en la obra1 el día 05-01-2003

El objetivo de la T-SQL es obtener los días que ha estado cada
uno de los códigos en cada una de las obras desde una fecha
determinada. Cuántos días hay que facturar a cada una de las
obras.

La última fecha de facturación fue el 31-12-2002 y la nueva
fecha es el 31-01-2003. Los resultados de facturación que se
desean obtener son.

Código Obra Desde
Hasta






Días
1 Obra1 01-01-2003 (Fecha de la
última facturación +1) 05-01-2003
5
1 Obra1 10-01-2003
31-01-2003 (Fecha de la facturación actual) 20
1 Obra4 05-01-2003
10-01-2003 4
2 Obra2 01-01-2003 (Fecha de la
última facturación +1) 31-01-2003 (Fecha de la
facturación actual) 31
4 Obra1 05-01-2003
31-01-2003 (Fecha de la facturación actual) 26

Gracias de antemano
Respuesta Responder a este mensaje
#10 Jose Antonio
04/11/2003 - 20:04 | Informe spam
Te explico mi problematica Javier.
Cuando tienes una tabla cabecera de pedidos por ejemplo y otra tabla de
lineas de pedidos, y entre la dos tienes una relacion para que las lineas se
eliminen en cascada si se elimina la cabecera del pedido.

Bien al tener definido un trigger en la tabla de lineas para que descuente
de la tabla de productos la cantidad que ya no esta pedida, me encuentro que
si anulas una linea del pedido la tabla deleted tiene una sola fila con lo
cual se lee el producto de esta fila y se le descuenta la cantidad de forma
correcta.

Pero cuando borras la cabecera del pedido la propia relacion de SQL se
encarga de anular las lineas del pedido y el trigger tambien se dipara
ahora, pero la tabla inserted tiene tantas filas como lineas tenia el
pedido.

Cada una con un producto diferente, entonces yo ahora utilizo un cursor
rapido de lectura solo hacia adelante para recorrer la tabla inserted. Y no
he encontrado otra solución por mas que la he buscado.

Si tienes una solución para esto sin cursores, te agradecería la expusieses
y yo tambien me uniria al club.

Saludos
Jose Antonio
"Javier Loria" escribió en el mensaje
news:
Hola Jose Antonio:
Mas que nada en un trigger NO deberias usar cursores. La razon es que


el
codigo del trigger "atraza" la transaccion, aumenta los bloqueos y en
general mata el rendimiento del servidor.
Efectivamente en los triggers las inserciones/actualizaciones y


borrados
son multiples, pero precisamente la fuerza de SQL esta en este tipo de
codigo.
Si nos mandas un ejemplo podemos trabajar con algo de codigo.
Saludos,


Javier Loria
Costa Rica
Se aprecia la inclusion de DDL (CREATE, INSERTS, etc.)
que pueda ser copiado y pegado al Query Analizer.
La version de SQL y Service Pack tambien ayuda.

Jose Antonio escribio:
> Da la impresión por vuestros comentarios, que nunca hay que usar
> cursores. Estoy de acuerdo que hay que intentar evitarlos, pero hay
> situaciones como en los triggers con inserciones, actualizaciones y
> borrados multiples donde son imprescindibles.
>
> Saludos.
> Jose Antonio
> "Miguel Egea" escribió en el mensaje
> news:
>> ¡Así me gusta Liliana! Creando adeptos.
>>
>> => >> Miguel Egea
>> http://www.portalsql.com
>> Microsoft SQL-SERVER MVP.
>> Brigada Anti-Cursores
>> Aviso de Seguridad
>>
>



http://www.microsoft.com/spain/tech...9-USER.asp
>> ==> >>
>> "Liliana Sorrentino" escribió en el
>> mensaje news:
>>> Hola,
>>> ¡Uno más para la brigada anti-cursores!
>>> Esto no es de lo mejor en plan de ejecución, pero depende también
>>> de la cantidad de información que manejes. Igual sigo trabajando a
>>> ver si puedo mejorarlo.
>>> Acabo de ver la propuesta de Javier, tendrás que ver los tiempos en
>>> función de la cantidad de datos.
>>> Saludos... Liliana.
>>>
>>> DECLARE @desde datetime, @hasta datetime
>>> SELECT @desde = '20030101', @hasta = '20030131'
>>> SELECT t1.codigo, t1.obra,
>>> CONVERT(CHAR(10), case when t1.fecha < @desde THEN @desde ELSE
>>> t1.fecha END, 112),
>>> CONVERT(CHAR(10), ISNULL((select min(fecha) from #tabla2 where
>>> t1.codigo = codigo AND t1.fecha < fecha), @hasta), 112),
>>> DATEDIFF(dd, CASE WHEN t1.fecha < @desde THEN @desde ELSE t1.fecha
>>> END, ISNULL((SELECT MIN(fecha) FROM #tabla2 WHERE t1.codigo
>>> = codigo AND t1.fecha < fecha), @hasta))
>>> FROM #tabla1 t1
>>> WHERE t1.fecha is not null
>>> UNION
>>> SELECT t2.codigo, t2.obra,
>>> CONVERT(CHAR(10), t2.fecha, 112),
>>> CONVERT(CHAR(10),
>>> ISNULL( (SELECT MIN(fecha) FROM #tabla1 WHERE t2.codigo > >>> codigo and t2.fecha < fecha),
>>> ISNULL( (SELECT MIN(fecha) FROM #tabla2 t22 WHERE t2.codigo > >>> t22.codigo and t2.fecha < t22.fecha), @hasta)), 112),
>>> DATEDIFF(dd, t2.fecha,
>>> ISNULL( (SELECT MIN(fecha) FROM #tabla1 WHERE t2.codigo > >>> codigo and t2.fecha < fecha),
>>> ISNULL( (SELECT MIN(fecha) FROM #tabla2 t22 WHERE t2.codigo > >>> t22.codigo and t2.fecha < t22.fecha), @hasta)))
>>> FROM #tabla2 t2
>>> ORDER BY 2, 3, 4, 5
>>>
>>> "cdiaz" escribió en el mensaje
>>> news:#
>>>> Cuando hablo de cursores hago referencia a SQL. Yo tiendo a
>>>> utilizar el típico algoritmo de recorrer hasta fin de fichero e ir
>>>> procesando registro a registro. Pues bien, leyendo mensajes de
>>>> este grupo (últimamente de Liliana Sorrentino) hay muchas
>>>> soluciones hechas con T-SQL que yo hubiera hecho con un cursor. Si
>>>> comparo los tiempos de respuesta entre el cursor y la T-SQL , ésta
>>>> última es mucho más rápida.
>>>>
>>>> Respecto a mi problema, se usan 2 tablas porque éstas proceden de
>>>> un sistema migrado de otras bases de datos. La Tabla1 serían los
>>>> datos maestros de los códigos y la Tabla2 serían los datos de los
>>>> movimientos del mes de dichos códigos. La Tabla1 contiene la fecha
>>>> y la obra de la situación a principio de mes del código. Existe
>>>> también en este sistema migrado un histórico de movimientos con
>>>> los registros así:
>>>>
>>>> Código Fecha Obra
>>>> 1 01-12-2002 Obra1
>>>> 1 05-01-2003 Obra4
>>>> 1 10-01-2003 Obra1
>>>> 2 05-07-2002 Obra2
>>>> 4 05-01-2003 Obra1
>>>>
>>>> Se lanza el proceso de facturación y el resultado se desea que sea
>>>> como el comentado en los anteriores mensajes. Si se puede obtener
>>>> el mismo resultado leyendo de este histórico serviría también. Hay
>>>> que tener en cuenta que en este histórico existen muchos registros
>>>> pues son los datos de los movimientos desde el año 96.
>>>>
>>>> Gracias
>>>>
>>>>
>>>> "Accotto Maximiliano Damian" escribió
>>>> en el mensaje news:uIIr%
>>>>> Hola!! 2 temas
>>>>>
>>>>> 1) vos cuando hablas de cursores hablas de SQL o de programacion
>>>>> como vb?
>>>>>
>>>>> Yo aconsejo no usar T-sql para programar ya que no es un lenguaje
>>>>> de programacion como VB,c# o alguno de ellos.
>>>>> Por mas que T-SQL nos permita hacer triggers y store, estos si se
>>>>> empiezan a complicar no es aconsejable usar T-SQL (por lo que lei
>>>>> en nuevas versiones de SQL tendra incorporado .Net).
>>>>>
>>>>> Bien pasando a tu problema porque no me explicas porque usas 2
>>>>> tablas y mejor aun el analisis del sistema, asi entiendo si el
>>>>> aplicar esas 2 tablas de esa forma es correcto o hay una forma
>>>>> mas optima de hacer la misma tarea.
>>>>>
>>>>> Un abrazo
>>>>>
>>>>> Accotto Maximiliano Damian
>>>>> "cdiaz" escribió en el mensaje
>>>>> news:
>>>>>> Dado que observo que las T-SQL son mucho más rápidas que los
>>>>>> cursoses me gustaría saber si el siguiente caso tendría una
>>>>>> buena solución con T-SQL. (ahora lo tengo hecho como un
>>>>>> procedimiento secuencial)
>>>>>>
>>>>>> Datos "reales"
>>>>>> << Tabla1 >>
>>>>>> Código Fecha Obra
>>>>>> 1 01-12-2002 Obra1
>>>>>> 2 05-07-2002 Obra2
>>>>>> 4 vacío vacío
>>>>>>
>>>>>> << Tabla 2 >>
>>>>>> Código Fecha Obra
>>>>>> 1 05-01-2003 Obra4
>>>>>> 1 10-01-2003 Obra1
>>>>>> 4 05-01-2003 Obra1
>>>>>>
>>>>>> El significado de estos datos es:
>>>>>>
>>>>>> El código 1 entró en la obra1 el 01-12-2002 y salió el
>>>>>> 05-01-2003 El código 1 entró en la obra4 el 05-01-2003 y salió
>>>>>> el 10-01-2003 El código 1 entró en la obra1 el 10-01-2003 y
>>>>>> todavía está en dicha obra1 El código 2 está en la obra2 desde
>>>>>> el 05-07-2002. Está todavía en la obra2. El código 4 ha
>>>>>> aparecido en la obra1 el día 05-01-2003
>>>>>>
>>>>>> El objetivo de la T-SQL es obtener los días que ha estado cada
>>>>>> uno de los códigos en cada una de las obras desde una fecha
>>>>>> determinada. Cuántos días hay que facturar a cada una de las
>>>>>> obras.
>>>>>>
>>>>>> La última fecha de facturación fue el 31-12-2002 y la nueva
>>>>>> fecha es el 31-01-2003. Los resultados de facturación que se
>>>>>> desean obtener son.
>>>>>>
>>>>>> Código Obra Desde
>>>>>> Hasta
>>> Días
>>>>>> 1 Obra1 01-01-2003 (Fecha de la
>>>>>> última facturación +1) 05-01-2003
>>>>>> 5
>>>>>> 1 Obra1 10-01-2003
>>>>>> 31-01-2003 (Fecha de la facturación actual) 20
>>>>>> 1 Obra4 05-01-2003
>>>>>> 10-01-2003 4
>>>>>> 2 Obra2 01-01-2003 (Fecha de la
>>>>>> última facturación +1) 31-01-2003 (Fecha de la
>>>>>> facturación actual) 31
>>>>>> 4 Obra1 05-01-2003
>>>>>> 31-01-2003 (Fecha de la facturación actual) 26
>>>>>>
>>>>>> Gracias de antemano


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