Problem bei Cursor / Schleife

01/04/2009 - 14:51 von AndreT78 | Report spam
Hallo,
Ich muss an Auftràgen Termine Verteilen. Die möglichen Termine habe ich in
einer extra Tabelle "Kapazitàt" (Datum, Kapazitàt in Stunden)
Jeder Auftrag hat eine Dauer.
Und nun soll ich die Termine der Reihenfolge nach an die Auftràge schreiben.
Wenn die Kapaziàt eines Tages erschöpft ist, ist halt der nàchste Tag dran.
Meiner Meinung nach, kann es nur irgendwie über eine Schleife / Cursor gehen.

Und da ist mein Problem. Die Dinger sind mir noch nicht so ganz vertraut.

Mein Ansatz ist folgender:
-Problem ist, wie frage ich den @Rest ab, so das ich die innere Schleife
wieder verlasse und einen Tag weiter gehe.


DECLARE Kapazitaet CURSOR FOR
SELECT id, cast(Stunden as float) Stunden
FROM
kapazitaet with (nolock)
where Datum >=getdate()

OPEN Kapazitaet
DECLARE @ID int
DECLARE @Std float

declare Auftraege Cursor for
select AuftragID, Dauer
from auftragstabelle with (nolock)

Open Auftraege
DECLARE @AuftragID int
DECLARE @dauer float
Declare @Rest float

FETCH NEXT FROM Kapazitaet INTO @ID, @Std

SET nocount on
BEGIN
WHILE @@FETCH_STATUS = 0
BEGIN

FETCH NEXT FROM Auftraege INTO @AuftragID, @dauer
SET nocount on

Begin
set @Rest = @Std
while @@Fetch_Status = 0
begin
set @Rest = @rest -@dauer


FETCH NEXT FROM Auftraege INTO @AuftragID, @Dauer
End
close Auftraege
end

FETCH NEXT FROM Kapazitaet INTO @ID, @Std
END
END


CLOSE Kapazitaet
DEALLOCATE Kapazitaet
DEALLOCATE Auftraege
 

Lesen sie die antworten

#1 Elmar Boye
02/04/2009 - 10:26 | Warnen spam
Hallo Andre,

AndreT78 schrieb:
Ich muss an Auftràgen Termine Verteilen. Die möglichen Termine habe ich in
einer extra Tabelle "Kapazitàt" (Datum, Kapazitàt in Stunden)
Jeder Auftrag hat eine Dauer.
Und nun soll ich die Termine der Reihenfolge nach an die Auftràge schreiben.
Wenn die Kapaziàt eines Tages erschöpft ist, ist halt der nàchste Tag dran.
Meiner Meinung nach, kann es nur irgendwie über eine Schleife / Cursor gehen.



Ich habe das unten auf die Schnelle zusammengebastelt.
Da man in solchen Fàllen normalerweise die Werte zurückschreiben muß,
sonst würde man immer von vorne planen, habe ich aktualisierbare Cursor
verwendet. Die genauen Details mußt Du an Deine Verhàltnisse anpassen.

Warnung: Da kann der eine oder andere Seiteneffekt oder Fehler drin sein,
da ich es nur runtertippt und minimal getestet habe.

Wenn Du Fragen zu den Einzelheiten hast, stelle sie.

Gruß Elmar

USE tempdb;
GO

CREATE TABLE dbo.Kapazitaet (
Id int NOT NULL PRIMARY KEY,
Datum datetime NOT NULL UNIQUE,
Stunden float NOT NULL);

CREATE TABLE dbo.Auftragstabelle (
AuftragID int NOT NULL PRIMARY KEY,
Dauer float NOT NULL,
Geplant bit NOT NULL);

SET NOCOUNT ON;
INSERT INTO dbo.kapazitaet VALUES(2, '20090402', 10);
INSERT INTO dbo.kapazitaet VALUES(3, '20090403', 5);
INSERT INTO dbo.kapazitaet VALUES(4, '20090404', 20);
INSERT INTO dbo.kapazitaet VALUES(1, '20090405', 10);

INSERT INTO dbo.Auftragstabelle VALUES (999, 15, 1); -- erledigt
INSERT INTO dbo.Auftragstabelle VALUES (1000, 5, 0);
INSERT INTO dbo.Auftragstabelle VALUES (1001, 6, 0);
INSERT INTO dbo.Auftragstabelle VALUES (1003, 8, 0);
INSERT INTO dbo.Auftragstabelle VALUES (1004, 5, 0);
INSERT INTO dbo.Auftragstabelle VALUES (1005, 15, 0);
GO

CREATE PROC dbo.KapazitaetZuordnung
AS
SET NOCOUNT ON;

DECLARE @ErrStatus int;
SET @ErrStatus = 0;


DECLARE KapazitaetCursor CURSOR
LOCAL KEYSET
FOR SELECT Stunden
FROM dbo.kapazitaet
WHERE Datum >= CONVERT(datetime, CONVERT(char(8), GETDATE(), 112))
ORDER BY Datum
FOR UPDATE OF Stunden;

DECLARE @KapazitaetID int;
DECLARE @KapazitaetStunden float;


DECLARE AuftraegeCursor CURSOR
LOCAL KEYSET
FOR SELECT Dauer
FROM dbo.Auftragstabelle
WHERE Geplant = 0
FOR UPDATE OF Geplant;

DECLARE @AuftraegeDauer float;


OPEN KapazitaetCursor;
FETCH NEXT FROM KapazitaetCursor INTO @KapazitaetStunden;
IF @@FETCH_STATUS = 0
BEGIN
OPEN AuftraegeCursor
FETCH NEXT FROM AuftraegeCursor INTO @AuftraegeDauer;

WHILE @ErrStatus = 0 AND @@FETCH_STATUS = 0
BEGIN
WHILE @KapazitaetStunden <= @AuftraegeDauer
BEGIN
SET @AuftraegeDauer = @AuftraegeDauer - @KapazitaetStunden

UPDATE dbo.Kapazitaet
SET Stunden = 0
WHERE CURRENT OF KapazitaetCursor
IF @@ERROR <> 0
BEGIN
SET @ErrStatus = -1;
BREAK;
END

FETCH NEXT FROM KapazitaetCursor INTO @KapazitaetStunden
IF @@FETCH_STATUS <> 0
BEGIN
SET @ErrStatus = 1;
BREAK; -- WHILE
END
END -- WHILE

IF @ErrStatus = 0
BEGIN
SET @KapazitaetStunden = @KapazitaetStunden - @AuftraegeDauer;
SET @AuftraegeDauer = 0;

IF @AuftraegeDauer = 0
BEGIN
UPDATE dbo.Auftragstabelle
SET Geplant = 1
WHERE CURRENT OF AuftraegeCursor;
IF @@ERROR <> 0
BEGIN
SET @ErrStatus = -1;
BREAK;
END
END
END;

IF @ErrStatus = 0
BEGIN
FETCH NEXT FROM AuftraegeCursor INTO @AuftraegeDauer;
END
END
END
IF @ErrStatus = 0
BEGIN
UPDATE dbo.Kapazitaet
SET Stunden = @KapazitaetStunden
WHERE CURRENT OF KapazitaetCursor
IF @@ERROR <> 0
BEGIN
SET @ErrStatus = -1;
END
END

CLOSE AuftraegeCursor
DEALLOCATE AuftraegeCursor

CLOSE KapazitaetCursor
DEALLOCATE KapazitaetCursor

IF @ErrStatus = -1 RETURN 1;
RETURN 0;
GO


SELECT (SELECT SUM(Stunden) FROM dbo.Kapazitaet) AS GesamtKapazitàt ,
(SELECT SUM(Dauer) AS GesamtDauer FROM dbo.Auftragstabelle WHERE Geplant = 0) AS GesamtDauer;
GO

EXECUTE dbo.KapazitaetZuordnung

SELECT (SELECT SUM(Stunden) FROM dbo.Kapazitaet) AS GesamtKapazitàt ,
(SELECT SUM(Dauer) AS GesamtDauer FROM dbo.Auftragstabelle WHERE Geplant = 0) AS GesamtDauer;
GO

DROP PROC dbo.KapazitaetZuordnung
GO
DROP TABLE dbo.Kapazitaet, dbo.Auftragstabelle;
GO

Ähnliche fragen