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:
Mostrar la cita
http://www.microsoft.com/spain/tech...9-USER.asp
Mostrar la cita
#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:
Mostrar la cita
alguien
Mostrar la cita
http://www.microsoft.com/spain/tech...9-USER.asp
Mostrar la cita
#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:%
Mostrar la cita
#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%
Mostrar la cita
un
Mostrar la cita
anteriores
Mostrar la cita
fecha
Mostrar la cita
eliminar
Mostrar la cita
#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:
Mostrar la cita
alguien
Mostrar la cita
http://www.microsoft.com/spain/tech...9-USER.asp
Mostrar la cita
Ads by Google
Search Busqueda sugerida