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

#11 Javier Loria
05/11/2003 - 01:20 | Informe spam
Hola Jose Antonio:
No se si esto estoy sobre-simplificando el problema. Pero asumamos:
/* Codigo de Creacion de Tablas DDL */
CREATE TABLE CabezasPedidos(
NumeroPedido INT NOT NULL
PRIMARY KEY
)

CREATE TABLE Productos(
NumeroProducto INT NOT NULL
PRIMARY KEY,
CantidadBackOrder INT NOT NULL
)

CREATE TABLE LineasPedidos(
NumeroPedido INT NOT NULL,
NumeroLineaPedido INT NOT NULL,
NumeroProducto INT NOT NULL,
CantidadOrdenada INT NOT NULL,
CONSTRAINT PK_LineasPedidos
PRIMARY KEY (NumeroPedido, NumeroLineaPedido),
CONSTRAINT FK_LineasCabezas
FOREIGN KEY (NumeroPedido)
REFERENCES CabezasPedidos(NumeroPedido)
ON DELETE CASCADE,
CONSTRAINT FK_LineasProducto
FOREIGN KEY (NumeroProducto)
REFERENCES Productos(NumeroProducto)
)
/* Fin de Codigo de Creacion de Tablas */
/* Insertar Datos Demo */
INSERT CabezasPedidos(NumeroPedido)
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4

INSERT Productos(NumeroProducto, CantidadBackOrder)
SELECT 10, 3 UNION ALL
SELECT 11, 7 UNION ALL
SELECT 12, 10 UNION ALL
SELECT 13, 10 UNION ALL
SELECT 14, 10

INSERT LineasPedidos(NumeroPedido, NumeroLineaPedido,
NumeroProducto, CantidadOrdenada)
SELECT 1,1,10,3 UNION ALL
SELECT 1,2,11,4 UNION ALL
SELECT 1,3,12,3 UNION ALL
SELECT 2,1,11,3 UNION ALL
SELECT 2,2,12,4 UNION ALL
SELECT 2,3,13,3 UNION ALL
SELECT 3,1,12,3 UNION ALL
SELECT 3,2,13,4 UNION ALL
SELECT 3,3,14,3 UNION ALL
SELECT 4,1,13,3 UNION ALL
SELECT 4,2,14,4
/* Fin de Insertar Datos Demo */

Este codigo crea las 3 tablas y sus relaciones; y un poco de datos.
El codigo del Trigger podria ser algo como:
/****************************************/
/* Trigger para Matener los BackOrder de Pedidos */
/****************************************/
CREATE TRIGGER Del_LineasPedidos
ON LineasPedidos
FOR DELETE
AS
BEGIN
IF EXISTS (SELECT * FROM Deleted)
BEGIN
UPDATE Productos
SET CantidadBackOrder=CantidadBackOrder-
CantidadOrdenada
FROM Productos JOIN
(SELECT NumeroProducto,
SUM(CantidadOrdenada) AS CantidadOrdenada
FROM Deleted
GROUP BY NumeroProducto) AS D ON
Productos.NumeroProducto=D.NumeroProducto
END
END

/**************/
/* Fin de Trigger */
/**************/
El Codigo de Trigger requiere un par de comentarios:
a) El IF EXISTS evita la propagacion de los Triggers. Ejemplo si alguien
ejecutara DELETE CabezasPedidos WHERE NumeroPedidos
b) El UPDATE usa una un SUBQUERY que agrupa las Lineas de Pedidos
Borradas (Deleted) por NumeroProducto porque es posible que existan varias
lineas del mismo producto en un Pedido o si se borran varios Pedidos
simultaneamente. Ejemplo todos los pedidos de un cliente.
c) En este codigo no estan implementada ninguna regla de negocio, pero
si hubiera alguna (CantidadBackOrder>0) entonces debes reportar el error
RAISEERROR y hacer ROLLBACK.

El codigo de pruebas:
/* Codigo de Prueba de Funcionalidad */
SELECT * FROM CabezasPedidos
SELECT * FROM Productos
SELECT * FROM LineasPedidos

DELETE CabezasPedidos
WHERE NumeroPedido=4
/* Fin Codigo de Prueba de Funcionalidad */

Espero te sirva.
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:
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
#12 Jose Antonio
05/11/2003 - 10:25 | Informe spam
Esto tiene buena pinta. Voy a hacer varias pruebas y te cuento.

Gracias y Saludos
Jose Antonio
"Javier Loria" escribió en el mensaje
news:
Hola Jose Antonio:
No se si esto estoy sobre-simplificando el problema. Pero asumamos:
/* Codigo de Creacion de Tablas DDL */
CREATE TABLE CabezasPedidos(
NumeroPedido INT NOT NULL
PRIMARY KEY
)

CREATE TABLE Productos(
NumeroProducto INT NOT NULL
PRIMARY KEY,
CantidadBackOrder INT NOT NULL
)

CREATE TABLE LineasPedidos(
NumeroPedido INT NOT NULL,
NumeroLineaPedido INT NOT NULL,
NumeroProducto INT NOT NULL,
CantidadOrdenada INT NOT NULL,
CONSTRAINT PK_LineasPedidos
PRIMARY KEY (NumeroPedido, NumeroLineaPedido),
CONSTRAINT FK_LineasCabezas
FOREIGN KEY (NumeroPedido)
REFERENCES CabezasPedidos(NumeroPedido)
ON DELETE CASCADE,
CONSTRAINT FK_LineasProducto
FOREIGN KEY (NumeroProducto)
REFERENCES Productos(NumeroProducto)
)
/* Fin de Codigo de Creacion de Tablas */
/* Insertar Datos Demo */
INSERT CabezasPedidos(NumeroPedido)
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4

INSERT Productos(NumeroProducto, CantidadBackOrder)
SELECT 10, 3 UNION ALL
SELECT 11, 7 UNION ALL
SELECT 12, 10 UNION ALL
SELECT 13, 10 UNION ALL
SELECT 14, 10

INSERT LineasPedidos(NumeroPedido, NumeroLineaPedido,
NumeroProducto, CantidadOrdenada)
SELECT 1,1,10,3 UNION ALL
SELECT 1,2,11,4 UNION ALL
SELECT 1,3,12,3 UNION ALL
SELECT 2,1,11,3 UNION ALL
SELECT 2,2,12,4 UNION ALL
SELECT 2,3,13,3 UNION ALL
SELECT 3,1,12,3 UNION ALL
SELECT 3,2,13,4 UNION ALL
SELECT 3,3,14,3 UNION ALL
SELECT 4,1,13,3 UNION ALL
SELECT 4,2,14,4
/* Fin de Insertar Datos Demo */

Este codigo crea las 3 tablas y sus relaciones; y un poco de datos.
El codigo del Trigger podria ser algo como:
/****************************************/
/* Trigger para Matener los BackOrder de Pedidos */
/****************************************/
CREATE TRIGGER Del_LineasPedidos
ON LineasPedidos
FOR DELETE
AS
BEGIN
IF EXISTS (SELECT * FROM Deleted)
BEGIN
UPDATE Productos
SET CantidadBackOrder=CantidadBackOrder-
CantidadOrdenada
FROM Productos JOIN
(SELECT NumeroProducto,
SUM(CantidadOrdenada) AS CantidadOrdenada
FROM Deleted
GROUP BY NumeroProducto) AS D ON
Productos.NumeroProducto=D.NumeroProducto
END
END

/**************/
/* Fin de Trigger */
/**************/
El Codigo de Trigger requiere un par de comentarios:
a) El IF EXISTS evita la propagacion de los Triggers. Ejemplo si


alguien
ejecutara DELETE CabezasPedidos WHERE NumeroPedidos
b) El UPDATE usa una un SUBQUERY que agrupa las Lineas de Pedidos
Borradas (Deleted) por NumeroProducto porque es posible que existan varias
lineas del mismo producto en un Pedido o si se borran varios Pedidos
simultaneamente. Ejemplo todos los pedidos de un cliente.
c) En este codigo no estan implementada ninguna regla de negocio, pero
si hubiera alguna (CantidadBackOrder>0) entonces debes reportar el error
RAISEERROR y hacer ROLLBACK.

El codigo de pruebas:
/* Codigo de Prueba de Funcionalidad */
SELECT * FROM CabezasPedidos
SELECT * FROM Productos
SELECT * FROM LineasPedidos

DELETE CabezasPedidos
WHERE NumeroPedido=4
/* Fin Codigo de Prueba de Funcionalidad */

Espero te sirva.
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:
> 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
#13 cdiaz
06/11/2003 - 09:33 | Informe spam
OK. Gracias. Pero ¿podría resolverse lo siguiente con cursores también?

Script de Creación de tablas

CREATE TABLE Tabla1(
Codigo INT NOT NULL ,
Fecha SMALLDATETIME NULL,
Obra VARCHAR(8) NULL,
Unidades INT
)

SET DATEFORMAT dmy
INSERT Tabla1(Codigo, Fecha,Obra, Unidades)
SELECT 1, '01-12-2002','Obra1', 6 UNION ALL
SELECT 1, '05-12-2002','Obra1', -4 UNION ALL
SELECT 1, '07-12-2002','Obra1', -2 UNION ALL
SELECT 1, '15-12-2002','Obra1', 3 UNION ALL
SELECT 2, '10-12-2002','Obra1', 20 UNION ALL
SELECT 2, '19-12-2002','Obra1', -1

La idea como verás sigue siendo facturar pero ahora se trata de facturar un
número determinado de unidades (campo unidades)
Tabla1 representa los movimientos de las unidades de cada código en cada
obra.
Suponiendo la fecha de facturación el 30-12-2002 sé hacer:

DECLARE @FecActualCierre datetime, @FecAnteriorCierre datetime
SELECT @FecAnteriorCierre = '20021201', @FecActualCierre '20021231'

Cuántas unidades quedaban en obra
select Codigo, Obra, MAX(Fecha), @FecActualCierre,
sum(Unidades) as TotUds
from Tabla1
group by Codigo, Obra
having sum(Unidades) <> 0
order by Codigo, Obra

y los periodos de facturación (igual que las T-SQL de los anteriores
mensajes)

SELECT T1.Codigo, T1.Obra, T1.Fecha as FechaEntradaObra,
MIN(T2.Fecha) AS FechaSalidaObra
FROM
Tabla1 T1
join
Tabla1 T2
ON T1.Codigo=T2.Codigo AND T1.Obra = T2.Obra and
T1.Fecha<T2.Fecha
GROUP BY T1.Codigo, T1.Obra, T1.Fecha

pero NO sé hacer las unidades que han estado en cada periodo.
Supongo que tendría que sumar las unidades para cada registro hasta la fecha
MIN(T2.Fecha) pero NO sé hacerlo de forma completa.

¿Alguna buena idea?
Gracias de antemano

"Javier Loria" escribió en el mensaje
news:%
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
#14 Javier Loria
06/11/2003 - 12:35 | Informe spam
Hola:
Creo que si, no se si entendi pero sera algo como:
SELECT T.Codigo,
T.Obra,
T.FechaEntradaObra,
T.FechaSalidaObra,
SUM(Tabla1.Unidades)
FROM
(SELECT T1.Codigo,
T1.Obra,
T1.Fecha as FechaEntradaObra,
MIN(T2.Fecha) AS FechaSalidaObra
FROM Tabla1 T1
JOIN Tabla1 T2
ON T1.Codigo=T2.Codigo AND
T1.Obra = T2.Obra AND
T1.Fecha<T2.Fecha
GROUP BY T1.Codigo, T1.Obra, T1.Fecha
) AS T
JOIN Tabla1 ON
T.Codigo=Tabla1.Codigo AND
T.Obra=T.Obra AND
T.FechaEntradaObra>=Tabla1.Fecha
GROUP BY T.Codigo,
T.Obra,
T.FechaEntradaObra,
T.FechaSalidaObra

No se si esto te da el resultado deseado?
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" wrote in message
news:%230o%
OK. Gracias. Pero ¿podría resolverse lo siguiente con cursores también?

Script de Creación de tablas

CREATE TABLE Tabla1(
Codigo INT NOT NULL ,
Fecha SMALLDATETIME NULL,
Obra VARCHAR(8) NULL,
Unidades INT
)

SET DATEFORMAT dmy
INSERT Tabla1(Codigo, Fecha,Obra, Unidades)
SELECT 1, '01-12-2002','Obra1', 6 UNION ALL
SELECT 1, '05-12-2002','Obra1', -4 UNION ALL
SELECT 1, '07-12-2002','Obra1', -2 UNION ALL
SELECT 1, '15-12-2002','Obra1', 3 UNION ALL
SELECT 2, '10-12-2002','Obra1', 20 UNION ALL
SELECT 2, '19-12-2002','Obra1', -1

La idea como verás sigue siendo facturar pero ahora se trata de facturar


un
número determinado de unidades (campo unidades)
Tabla1 representa los movimientos de las unidades de cada código en cada
obra.
Suponiendo la fecha de facturación el 30-12-2002 sé hacer:

DECLARE @FecActualCierre datetime, @FecAnteriorCierre datetime
SELECT @FecAnteriorCierre = '20021201', @FecActualCierre > '20021231'

Cuántas unidades quedaban en obra
select Codigo, Obra, MAX(Fecha), @FecActualCierre,
sum(Unidades) as TotUds
from Tabla1
group by Codigo, Obra
having sum(Unidades) <> 0
order by Codigo, Obra

y los periodos de facturación (igual que las T-SQL de los


anteriores
mensajes)

SELECT T1.Codigo, T1.Obra, T1.Fecha as FechaEntradaObra,
MIN(T2.Fecha) AS FechaSalidaObra
FROM
Tabla1 T1
join
Tabla1 T2
ON T1.Codigo=T2.Codigo AND T1.Obra = T2.Obra and
T1.Fecha<T2.Fecha
GROUP BY T1.Codigo, T1.Obra, T1.Fecha

pero NO sé hacer las unidades que han estado en cada periodo.
Supongo que tendría que sumar las unidades para cada registro hasta la


fecha
MIN(T2.Fecha) pero NO sé hacerlo de forma completa.

¿Alguna buena idea?
Gracias de antemano

"Javier Loria" escribió en el mensaje
news:%
> 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
#15 Jose Antonio
07/11/2003 - 17:20 | Informe spam
Javier, funciona perfectamente.
Gracias por la información.

Saludos.
Jose Antonio
"Javier Loria" escribió en el mensaje
news:
Hola Jose Antonio:
No se si esto estoy sobre-simplificando el problema. Pero asumamos:
/* Codigo de Creacion de Tablas DDL */
CREATE TABLE CabezasPedidos(
NumeroPedido INT NOT NULL
PRIMARY KEY
)

CREATE TABLE Productos(
NumeroProducto INT NOT NULL
PRIMARY KEY,
CantidadBackOrder INT NOT NULL
)

CREATE TABLE LineasPedidos(
NumeroPedido INT NOT NULL,
NumeroLineaPedido INT NOT NULL,
NumeroProducto INT NOT NULL,
CantidadOrdenada INT NOT NULL,
CONSTRAINT PK_LineasPedidos
PRIMARY KEY (NumeroPedido, NumeroLineaPedido),
CONSTRAINT FK_LineasCabezas
FOREIGN KEY (NumeroPedido)
REFERENCES CabezasPedidos(NumeroPedido)
ON DELETE CASCADE,
CONSTRAINT FK_LineasProducto
FOREIGN KEY (NumeroProducto)
REFERENCES Productos(NumeroProducto)
)
/* Fin de Codigo de Creacion de Tablas */
/* Insertar Datos Demo */
INSERT CabezasPedidos(NumeroPedido)
SELECT 1 UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4

INSERT Productos(NumeroProducto, CantidadBackOrder)
SELECT 10, 3 UNION ALL
SELECT 11, 7 UNION ALL
SELECT 12, 10 UNION ALL
SELECT 13, 10 UNION ALL
SELECT 14, 10

INSERT LineasPedidos(NumeroPedido, NumeroLineaPedido,
NumeroProducto, CantidadOrdenada)
SELECT 1,1,10,3 UNION ALL
SELECT 1,2,11,4 UNION ALL
SELECT 1,3,12,3 UNION ALL
SELECT 2,1,11,3 UNION ALL
SELECT 2,2,12,4 UNION ALL
SELECT 2,3,13,3 UNION ALL
SELECT 3,1,12,3 UNION ALL
SELECT 3,2,13,4 UNION ALL
SELECT 3,3,14,3 UNION ALL
SELECT 4,1,13,3 UNION ALL
SELECT 4,2,14,4
/* Fin de Insertar Datos Demo */

Este codigo crea las 3 tablas y sus relaciones; y un poco de datos.
El codigo del Trigger podria ser algo como:
/****************************************/
/* Trigger para Matener los BackOrder de Pedidos */
/****************************************/
CREATE TRIGGER Del_LineasPedidos
ON LineasPedidos
FOR DELETE
AS
BEGIN
IF EXISTS (SELECT * FROM Deleted)
BEGIN
UPDATE Productos
SET CantidadBackOrder=CantidadBackOrder-
CantidadOrdenada
FROM Productos JOIN
(SELECT NumeroProducto,
SUM(CantidadOrdenada) AS CantidadOrdenada
FROM Deleted
GROUP BY NumeroProducto) AS D ON
Productos.NumeroProducto=D.NumeroProducto
END
END

/**************/
/* Fin de Trigger */
/**************/
El Codigo de Trigger requiere un par de comentarios:
a) El IF EXISTS evita la propagacion de los Triggers. Ejemplo si


alguien
ejecutara DELETE CabezasPedidos WHERE NumeroPedidos
b) El UPDATE usa una un SUBQUERY que agrupa las Lineas de Pedidos
Borradas (Deleted) por NumeroProducto porque es posible que existan varias
lineas del mismo producto en un Pedido o si se borran varios Pedidos
simultaneamente. Ejemplo todos los pedidos de un cliente.
c) En este codigo no estan implementada ninguna regla de negocio, pero
si hubiera alguna (CantidadBackOrder>0) entonces debes reportar el error
RAISEERROR y hacer ROLLBACK.

El codigo de pruebas:
/* Codigo de Prueba de Funcionalidad */
SELECT * FROM CabezasPedidos
SELECT * FROM Productos
SELECT * FROM LineasPedidos

DELETE CabezasPedidos
WHERE NumeroPedido=4
/* Fin Codigo de Prueba de Funcionalidad */

Espero te sirva.
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:
> 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