Abfrage

Abfrage

am 09.08.2006 17:10:50 von Andrea

Hallo NG,
ich habe folgenden Tabellenaufbau:
zr_von ; zr_bis ; gueltig_ab ; gueltig_bis ; Wert
01.01.06 ; 31.12.06 ; 04.08.06 ; 08.08.06 ; 5
01.01.06 ; 31.12.06 ; 08.06.06 ; NULL ; 6
01.01.07 ; 31.12.07 ; 04.08.06 ; 06.08.06 ; 5
01.01.07 ; 31.12.07 ; 06.08.06 ; NULL ; 7

Meine Abrage dazu lautet:

SELECT zr_von, zr_bis, gueltig_ab, Wert
FROM Tabelle WHERE
gueltig_ab = (SELECT MAX(gueltig_ab) FROM Tabelle A
WHERE A.zr_von = zr_von AND A.zr_bis = zr_bis
AND gueltig_ab <= 09.08.2006 AND (gueltig_bis IS NULL
OR gueltig_bis > '09.08.2006'))

Als Ergebnis bekomme ich aber immer nur den Zeitraum von 2006, da dort das
globale maximale 'gueltig_ab' liegt. Ich möchte aber das maximale
'gueltig_ab' für jeden Zeitraum ausgegeben haben. Ich dachte, dass ich dies
mit
A.zr_von = zr_von AND A.zr_bis = zr_bis ereichen kann. Leider funktioniert
es so nicht.
Was muss ich aendern?

Gruß
Andrea

Re: Abfrage

am 09.08.2006 18:38:08 von Thomas Rachel

Andrea wrote:

> Hallo NG,
> ich habe folgenden Tabellenaufbau:
> zr_von ; zr_bis ; gueltig_ab ; gueltig_bis ; Wert
> 01.01.06 ; 31.12.06 ; 04.08.06 ; 08.08.06 ; 5
> 01.01.06 ; 31.12.06 ; 08.06.06 ; NULL ; 6
> 01.01.07 ; 31.12.07 ; 04.08.06 ; 06.08.06 ; 5
> 01.01.07 ; 31.12.07 ; 06.08.06 ; NULL ; 7

Wenn Du die Daten so abspeicherst, fällst Du auf die ein oder andere Weise
auf die Nase.

MySQL hat einen eigenen Datentyp für Kalenderdatumswerte. Bei diesem wird
ein Datum in der Form YYYY-MM-DD oder YYYYMMDD gespeichert.

In der von Dir gewählten Form läßt sich ein Datum nur als varchar speichern
- aber da schlägt das Kopieren fehl, da die DD.MM.YYYY-Schreibweise sehr
sortierunfreundlich ist.

MySQL hat auch Funktionen für diese Konvertierung, die Du für die nun
notwendige Umstellung der Datenbank, für die Eingabe neuer Daten und auch .
Näheres findest Du im Handbuch unter http://dev.mysql.com.


Nehmen wir mal an, Du hättest die Sache nun schon umgestellt. Dann sieht das
Ganze so aus:

create temporary table Tabelle (zr_von date, zr_bis date, gueltig_ab date,
gueltig_bis date, wert int);
insert into Tabelle values (20060101,20061231, 20060804, 20060808, 5)
(20060101,20061231, 20060608, NULL, 6),(20070101,20071231, 20060804,
20060806, 5),(20070101,20071231, 20060806, NULL, 7);
select * from Tabelle;
+------------+------------+------------+-------------+------ +
| zr_von | zr_bis | gueltig_ab | gueltig_bis | wert |
+------------+------------+------------+-------------+------ +
| 2006-01-01 | 2006-12-31 | 2006-08-04 | 2006-08-08 | 5 |
| 2006-01-01 | 2006-12-31 | 2006-06-08 | NULL | 6 |
| 2007-01-01 | 2007-12-31 | 2006-08-04 | 2006-08-06 | 5 |
| 2007-01-01 | 2007-12-31 | 2006-08-06 | NULL | 7 |
+------------+------------+------------+-------------+------ +

Bei Wert 6 meintest Du aber sicherlich den 8. August, nicht den 8. Juni,
oder?

Also korrigieren wir:

update Tabelle set gueltig_ab='2006-08-08' where wert=6;

Und weil temporäre Tabellen sich nicht mehrfach verwenden lassen, erstellen
wir grad mal eine zusätzliche und modifizieren den Query, indem wir Tabelle
A zu A machen:

CREATE TEMPORARY TABLE A SELECT * FROM Tabelle;

SELECT zr_von, zr_bis, gueltig_ab, Wert FROM Tabellle WHERE gueltig_ab =
(SELECT MAX(gueltig_ab) FROM /* Tabelle */ A WHERE A.zr_von = zr_von AND
A.zr_bis = zr_bis AND gueltig_ab <= '2006-08-09' AND (gueltig_bis IS NULL
OR gueltig_bis > '2006-08-09'));

Hier bekomme ich:

+------------+------------+------------+------+
| zr_von | zr_bis | gueltig_ab | Wert |
+------------+------------+------------+------+
| 2007-01-01 | 2007-12-31 | 2006-08-06 | 7 |
+------------+------------+------------+------+

> Ich möchte aber das maximale 'gueltig_ab' für jeden Zeitraum ausgegeben
> haben. Ich dachte, dass ich dies mit A.zr_von = zr_von AND A.zr_bis =
> zr_bis ereichen kann. Leider funktioniert es so nicht.

Vermutung: Suchtest Du vielleicht

SELECT zr_von, zr_bis, MAX(gueltig_ab) FROM Tabelle GROUP BY zr_von,zr_bis

?
+------------+------------+-----------------+
| zr_von | zr_bis | MAX(gueltig_ab) |
+------------+------------+-----------------+
| 2006-01-01 | 2006-12-31 | 2006-08-04 |
| 2007-01-01 | 2007-12-31 | 2006-08-06 |
+------------+------------+-----------------+


Nein, Du hattest oben ja noch eine Bedingung drin ('Heute' heißt in MySQL
übrigens CURRENT_DATE(), steht aber auch im Handbuch). Also ergänzen wir:

SELECT zr_von, zr_bis, MAX(gueltig_ab) AS seit
FROM Tabelle
WHERE gueltig_ab <= CURRENT_DATE() AND
(COALESCE(gueltig_bis,'9999-12-31') > CURRENT_DATE())
GROUP BY zr_von,zr_bis;
+------------+------------+------------+
| zr_von | zr_bis | seit |
+------------+------------+------------+
| 2006-01-01 | 2006-12-31 | 2006-08-08 |
| 2007-01-01 | 2007-12-31 | 2006-08-06 |
+------------+------------+------------+

Erläuterung:
1. Der Spaltenname "seit" ist besser als "MAX(gueltig_ab)".
2. COALESCE gibt den ersten nicht-NULL-nen Wert seiner Parameterliste
zurück. Sprich: Ist gueltig_bis NULL, wird stattdessen '9999-12-31'
zurückgegeben.

HTH,

Thomas
--
Sig lost.