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

#1 Accotto Maximiliano Damian
30/10/2003 - 13:37 | Informe spam
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:
Mostrar la cita
obra2.
Mostrar la cita
actual)
Mostrar la cita
#2 cdiaz
30/10/2003 - 16:21 | Informe spam
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%
Mostrar la cita
a
Mostrar la cita
tablas
Mostrar la cita
tarea.
Mostrar la cita
T-SQL.
Mostrar la cita
obra1
Mostrar la cita
los
Mostrar la cita
días
Mostrar la cita
#3 Javier Loria
30/10/2003 - 17:19 | Informe spam
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:
Mostrar la cita
#4 Liliana Sorrentino
30/10/2003 - 18:12 | Informe spam
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:#
Mostrar la cita
a
Mostrar la cita
Liliana
Mostrar la cita
con
Mostrar la cita
,
Mostrar la cita
sistema
Mostrar la cita
los
Mostrar la cita
resultado
Mostrar la cita
vb?
Mostrar la cita
empiezan
Mostrar la cita
versiones
Mostrar la cita
me
Mostrar la cita
el
Mostrar la cita
Días
Mostrar la cita
#5 Miguel Egea
01/11/2003 - 21:35 | Informe spam
¡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:
Mostrar la cita
función
Mostrar la cita
registro
Mostrar la cita
T-SQL
Mostrar la cita
dichos
Mostrar la cita
principio
Mostrar la cita
de
Mostrar la cita
el
Mostrar la cita
en
Mostrar la cita
y
Mostrar la cita
cursoses
Mostrar la cita
la
Mostrar la cita
de
Mostrar la cita
Cuántos
Mostrar la cita
última
Mostrar la cita
última
Mostrar la cita
Ads by Google
Search Busqueda sugerida