| 

.NET C# Java Javascript Exception

2
Folgendes Problem im SQL Server mit einem kleinen Beispielcode:

Ich habe eine Tabelle mit mehreren Datensätze (hier: #preise), wo jeweils ein Wert in einem Gültigkeitsbereich (datumvon und datumbis) definiert ist. Hier im Beispiel: Ein Preis ist gültig von ... bis ...

Jetzt würde ich daraus gerne eine Tabelle erzeugen, wo diese Werte pro Tag übernommen werden.

Der UPDATE-Befehl macht aber in diesem Fall einfach irgendwas, was gültig sein könnte:
2012-01-24 = 10
2012-01-25 = 10
2012-01-26 = 30
2012-01-27 = 10
2012-01-28 = 30
2012-01-29 = 10
2012-01-30 = 30
2012-01-31 = 10
2012-02-01 = 30
2012-02-02 = 20
2012-02-03 = 30

Kann ich bei dem UPDATE irgendwie eine Priorität festlegen, welcher Satz gewinnen würde, wenn der Wert nicht eindeutig ist? Im Idealfall sollte der Wert gewinnen, bei dem der Zeitraum am Kürzesten ist.

Als Beispiel: Ein Preis ist für das komplette Jahr 2012 festgelegt. Für eine Sonderaktion gilt aber für einen Zeitraum von 10 Tagen ein Sonderpreis. Beim UPDATE sollte nun dieser Sonderpreis "gewinnen", obwohl der Zeitraum sich mit dem Jahreszeitraum 2012 auch überschneidet.

CREATE TABLE #preisprotag ( datum date, preis int );

DECLARE @datum date;
SET @datum = '2012-01-01';

WHILE ( @datum <= '2012-12-31')
BEGIN
INSERT INTO #preisprotag ( datum, preis ) VALUES ( @datum, 0 );
SET @datum = DATEADD(DAY, 1, @datum);
END

CREATE TABLE #preise ( datumvon date, datumbis date, preis int );
INSERT INTO #preise ( datumvon, datumbis, preis ) VALUES ( '2012-01-01', '2012-01-31', 10 );
INSERT INTO #preise ( datumvon, datumbis, preis ) VALUES ( '2012-02-01', '2012-02-29', 20 );
INSERT INTO #preise ( datumvon, datumbis, preis ) VALUES ( '2012-01-25', '2012-02-05', 30 );

UPDATE #preisprotag SET preis = #preise.preis
FROM #preise
WHERE #preisprotag.datum BETWEEN #preise.datumvon AND #preise.datumbis;

SELECT * FROM #preisprotag;

DROP TABLE #preisprotag;
DROP TABLE #preise;
10.04.2012
commänder 420 1 7
2 Antworten
0
Hallo,

als erstes mal meine persönlich Meinung zusammengefasst: ganz schöner Murks den Du da machen willst. In die Businesslogik, da genau gehört meiner Meinung nach Deine Problembehandlung hin, und nicht in die Datenbank.

Aber da ich in einer Dienstleistungsgesellschaft lebe hier ein Ansatz:

Da Deine Daten ja keinerlei Eindeutigkeit zulassen bleibt Dir also nur die Variante nach der "Laufzeit" zu gehen, was alles andere als gut ist.

SELECT TOP 1
datumvon,
datumbis,
preis,
CAST(datumbis AS INTEGER) - CAST(datumvon AS INTEGER) AS zeitraum
FROM preise
WHERE datumvon <= @mein_zeitpunkt
AND datumbis >= @mein_zeitpunkt
ORDER BY zeitraum


Damit bekommst Du alle Datensätze mit der kleinsten "Laufzeit" zu einem Zeitpunkt. Ich spreche hier bewusst in der Mehrzahl, da z.B. vier Preise zu einem Zeitpunkt "gültig sind", zwar einen unterschiedlichen Zeitraum haben, aber eine gleichlange Laufzeit.

Vll. hilft Dir das ja weiter.

PS.: wie bitte schaffst Du es eine Tabelle á la "#preise" zu haben, da bekomme ich eine Fehlermeldung, da der Name nicht erlaubt ist.
10.04.2012
SensenMannLE 1,2k 2 9
Danke für Deine Hinweise.

Die angegebenen Daten waren nur ein extrem stark vereinfachtes Beispiel. Eigentlich geht es um ein anderes Problem, nämlich um die Berechnung von Arbeitsplänen für Mitarbeiter.

Ein Mitarbeiter hat einen Stammarbeitsplan. Der Arbeitsplan kann aber jahresweise, monatsweise, wochenweise oder tageweise wechseln, oder aber auch für einen beliebigen Zeitraum, gepaart mit automatisch Rythmen (Wechsel alle 2 Wochen, alle ungeraden Wochen, etc.). Das steht auch sauber in verschiedenen Tabellen drin.
commänder 10.04.2012
Die Überschneidungen ergeben sich einfach durch die eingetragenen Wechsel. Ein sauberes Auftrennen und Vermeiden von Überlappungen wäre zwar in der Business Logik möglich, aber für den Anwender viel zu unübersichtlich.

Der Anwender gibt ein: Die nächsten 3 Monate wird halbtags vormittags gearbeitet, aber in 2 Wochen wird mal ein paar Tage nachmittags statt vormittags gearbeitet. Würde ich nun in der Datenbank die Datensätze überschneidungsfrei auftrennen, versteht das kein Anwender.
commänder 10.04.2012
Vor allem gibt das dann wieder Probleme, wenn ein Wechsel dann doch wieder gelöscht wird, dann müssten die anderen Wechsel ja wieder zusammengeführt werden. Also speichere ich die Werte so, wie diese eingegeben wurden. Und die Überschneidungen müssen dann eben aufgelöst werden.

Da die Wechsel sehr häufig vorkommen, werden meine Views auch sehr komplex und langsam, um festzustellen, wer wann arbeitet. Die Views funktionieren zwar problemlos, aber eben aufgrund der Komplexität sehr langsam.
commänder 10.04.2012
Da die Views sehr häufig zur Visualisierung abgerufen werden, wollte ich mir hier eine Optimierung überlegen.

Die Idee war daher, eine Tabelle einzuführen, die via Trigger automatisch aktualisiert wird, so dass hier der pro Tag gültige Arbeitsplan vorberechnet wird, um komplexe JOINs in den übrigen Views zu vermeiden. So wäre dann nur noch ein simpler SELECT auf eine Tabelle notwendig, anstatt komplexer JOINs über 5 Tabellen hinweg.

Ich dachte mir nur, anhand des Hilfsmittels "Preise" wäre es leichter zu erklären ;-)

PS: Das Script im SQL Server 2008 R2 läuft bei mir problemlos durch...
commänder 10.04.2012
PPS: Warum dürfen Kommentare eigentlich nur 600 Zeichen lang sein???
commänder 10.04.2012
Ok, Arbeitsplanzeiten müssen nicht rechtssicher sein, das entschärft die Thematik. Ich denke schon, dass es möglich ist, für den Anwender es so zu gestalten, dass dieser noch durchblickt, aber in der Datenbank alles sauber getrennt ist. Die Businesslogik muss dann halt einiges mehr "wett machen". Aber solange Du eine für Dich funktionierende Lösung hast, ist alles im Lot.
SensenMannLE 10.04.2012
0
Inzwischen habe ich eine Lösung gefunden:

WITH temp AS
(
SELECT TOP 999999 * FROM #preise ORDER BY DATEDIFF(DAY,datumvon,datumbis) ASC
)
UPDATE #preisprotag SET preis = temp.preis
FROM temp
WHERE #preisprotag.datum BETWEEN temp.datumvon AND temp.datumbis
OPTION ( FORCE ORDER )
10.04.2012
commänder 420 1 7

Stelle deine Sql-server-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH