Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

SQL Abfrage zur Preisberechnung unter Beachtung des Datums

57 views
Skip to first unread message

Sascha Vetter

unread,
Jun 14, 2004, 8:16:25 AM6/14/04
to
Hallo,

leider hat mir ein Wochenende und mehrere Stunden Groups- u.
Googlesuche nicht weitergeholfen um folgendes Problem zu lösen:

Also wir haben eine Tabelle:
up_id int(10) auto_increment
up_datum date
up_preis float
up_uzid int(10)

In der Tabelle steht sowas wie unten drin:
1 0000-00-00 19 1
2 2004-12-24 25.5 1

Der Sinn der Sache: Also in der Tabelle sind die Preise für die
verschiedenen Zimmer vermerkt, Standartpreis ist das mit dem Datum
"0000-00-00", also hier 19 Euro. Natürlich gibt es aber auch Tage die
teurer sind, wie z.B. hier der "2004-12-24".

Nun möchte ich einen Insgesamtpreis berechen, der Abfrage wird
übergeben an welchen Tagen der Besucher da ist und ich erwarte den
Preis für den Aufenthalt zurück. Also z.B. will der Besucher vom
23.12.04 bis 27.12.04 bleiben, dann wird an jedem Tag, bis auf dem
24zigsten der Standartpreis genommen und einmal halt der Extrapreis,
den Insgesamtpreis erwarte ich dann zurück.

Ist das möglich per Abfragen herauszubekommen? Muss ich die Tabelle
umstellen um dies zu ermöglichen?

Danke im Voraus für ein paar Anregungen und Lösungsvorschläge.

Marian Heddesheimer

unread,
Jun 14, 2004, 11:37:05 AM6/14/04
to
On 14 Jun 2004 05:16:25 -0700, sav...@yahoo.de (Sascha Vetter) wrote:

>Der Sinn der Sache: Also in der Tabelle sind die Preise für die
>verschiedenen Zimmer vermerkt, Standartpreis ist das mit dem Datum
>"0000-00-00", also hier 19 Euro. Natürlich gibt es aber auch Tage die
>teurer sind, wie z.B. hier der "2004-12-24".

irgendeine Schule hat das wohl gerade als Hausaufgabe. Neulich hatte
ich schon mal so eine Frage gesehen ;-)

select * from hotelpreise where up_datum between '2004-12-23' and
'2004-12-24'

Damit bekommst du alle Tage, die vom Standardpreis abweichen. Alles
andere wirst Du wohl per Programm errechnen müssen, oder für jeden
einzelnen Tag auch den Standardpreis in der Tabelle abspeichern
müssen.

Gruß

Marian

--
Tipps und Tricks zu PHP, Coaching und Projektbetreuung
http://www.heddesheimer.de/coaching/

Harald Fuchs

unread,
Jun 15, 2004, 12:27:28 PM6/15/04
to
In article <26654d80.04061...@posting.google.com>,
sav...@yahoo.de (Sascha Vetter) writes:

Die Tatsache, daß MySQL "0000-00-00" als gültiges Datum akzeptiert,
ist ein übles Misfeature, wofür die Entwickler gesteinigt gehören.
Nimm stattdessen NULL.

Solche Abfragen mache ich üblicherweise mit einer "erwachsenen"
Datenbank und suche mir dann die passenden MySQL-Workarounds heraus.
In PostgreSQL z.B. könnte man das so lösen:

CREATE OR REPLACE FUNCTION enum (DATE, DATE) RETURNS SETOF DATE AS '
DECLARE
d1 DATE;
d2 ALIAS FOR $2;
BEGIN
d1 := $1;
WHILE d1 <= d2 LOOP
RETURN NEXT d1;
d1 := d1 + INTERVAL ''1 day'';
END LOOP;
RETURN;
END
' LANGUAGE 'plpgsql' IMMUTABLE;

SELECT sum (coalesce (r.up_preis,
(SELECT up_preis FROM rates WHERE up_datum IS NULL)))
FROM enum ('2004-12-23'::date, '2004-12-27'::date) AS d (dt)
LEFT JOIN rates r ON r.up_datum = d.dt;

In MySQL 5.x dürfte das ähnlich gehen. Bis dahin brauchen wir zwei
Workarounds: erstens für die Stored Procedure, die die Tage erzeugt,
und zweitens für die Subquery, die den Standardpreis herausfindet.

Ersteres läßt sich durch eine Hilfstabelle erledigen:

CREATE TABLE dates (
dt DATE NOT NULL,
PRIMARY KEY (dt)
);

...
INSERT INTO dates (dt) VALUES ('2004-12-21');
INSERT INTO dates (dt) VALUES ('2004-12-22');
INSERT INTO dates (dt) VALUES ('2004-12-23');
INSERT INTO dates (dt) VALUES ('2004-12-24');
INSERT INTO dates (dt) VALUES ('2004-12-25');
INSERT INTO dates (dt) VALUES ('2004-12-26');
INSERT INTO dates (dt) VALUES ('2004-12-27');
INSERT INTO dates (dt) VALUES ('2004-12-28');
...

In der Praxis würde man diese Tabelle natürlich nur einmal anlegen und
alle Tage bis in ein paar Jahren eintragen. Die Query sähe dann wie
folgt aus:

SELECT sum (coalesce (r.up_preis,
(SELECT up_preis FROM rates WHERE up_datum IS NULL)))
FROM dates d
LEFT JOIN rates r ON r.up_datum = d.dt
WHERE d.dt BETWEEN '2004-12-23' AND '2004-12-27';

Das funktioniert zwar mit MySQL 4.1.x, aber diese Version hat noch
zuviele Bugs. Für MySQL 4.0.x müssen wir noch die Subquery
loswerden. Dazu bieten sich Benutzervariablen an:

SELECT @dflt := up_preis AS dflt
FROM rates
WHERE up_datum IS NULL;

SELECT sum (coalesce (r.up_preis, @dflt)) AS sum
FROM dates d
LEFT JOIN rates r ON r.up_datum = d.dt
WHERE d.dt BETWEEN '2004-12-23' AND '2004-12-27';

Ist dann halt nicht mehr eine Query, aber anders geht es wohl nicht.

Sascha Vetter

unread,
Jun 22, 2004, 10:26:29 AM6/22/04
to
Hallo Herr Fuchs,

als DB dient MySQL 3.23.49. Ihr Beitrag hat mich zwar weiter gebracht
aber die Lösung war so nicht möglich, mein Status z.Z.:

Also ich hab die Datenbank mal geteilt, nun gibts

Tabelle: u_zimmer
uz_id int(10) auto increment
uz_stpreis float

Tabelle: u_preise


up_id int(10) auto_increment
up_datum date
up_preis float
up_uzid int(10)

Also dann gib es nun den Standartpreis jedes Zimmers im Feld
"uz_stpreis" und die Extrapreise in der Tabelle "u_preise" unter
"up_preis" mit dem ensprechenden Tag "up_datum".

Nun gibt z.B. den Eintrag
Tabelle: u_zimmer
uz_id = 1
uz_stpreis = 15.35

Tabelle: u_preise
up_id = 1
up_datum = 2004-12-25
up_preis = 17.3
up_uzid = 1

Tabelle: u_preise
up_id = 1
up_datum = 2004-12-26
up_preis = 18.5
up_uzid = 1

Wie wäre es nun möglich den Insgesamtpreis des Aufenthalts vom
2004-12-22 bis 2004-12-28 zu berechnen? Bitte beachten Sie dass auch
noch mehr Zimmer dazu kommen können. Ist eine Lösung per SQL überhaupt
möglich?

Harald Fuchs

unread,
Jun 22, 2004, 12:09:45 PM6/22/04
to
In article <26654d80.04062...@posting.google.com>,
sav...@yahoo.de (Sascha Vetter) writes:

> Hallo Herr Fuchs,

Kannst mich ruhig duzen - das ist im Usenet so üblich.

> als DB dient MySQL 3.23.49. Ihr Beitrag hat mich zwar weiter gebracht
> aber die Lösung war so nicht möglich, mein Status z.Z.:

> Also ich hab die Datenbank mal geteilt, nun gibts

> Tabelle: u_zimmer
> uz_id int(10) auto increment
> uz_stpreis float

> Tabelle: u_preise
> up_id int(10) auto_increment
> up_datum date
> up_preis float
> up_uzid int(10)

Auf gar keinen Fall FLOAT für Beträge verwenden!!! Rundungsfehler
vermeidet man durch NUMERIC oder durch Cent-Beträge in INT.

> Also dann gib es nun den Standartpreis jedes Zimmers im Feld
> "uz_stpreis" und die Extrapreise in der Tabelle "u_preise" unter
> "up_preis" mit dem ensprechenden Tag "up_datum".

> Nun gibt z.B. den Eintrag
> Tabelle: u_zimmer
> uz_id = 1
> uz_stpreis = 15.35

> Tabelle: u_preise
> up_id = 1
> up_datum = 2004-12-25
> up_preis = 17.3
> up_uzid = 1

> Tabelle: u_preise
> up_id = 1

Ich nehme an, das muß up_id = 2 heißen. Ich würde aber diese wohl
überflüssige Spalte komplett löschen und stattdessen die Kombination
aus Datum und ZimmerID als Primary Key verwenden.

> up_datum = 2004-12-26
> up_preis = 18.5
> up_uzid = 1

> Wie wäre es nun möglich den Insgesamtpreis des Aufenthalts vom
> 2004-12-22 bis 2004-12-28 zu berechnen? Bitte beachten Sie dass auch
> noch mehr Zimmer dazu kommen können. Ist eine Lösung per SQL überhaupt
> möglich?

Naja, genau wie ich vorher gesagt habe, nur eben mit der ZimmerID mit drin:

SELECT @dflt := uz_stpreis AS dflt
FROM u_zimmer
WHERE uz_id = 1;

SELECT sum (coalesce (r.up_preis, @dflt)) AS sum
FROM dates d

LEFT JOIN u_preise r ON r.up_datum = d.dt AND r.up_uzid = 1
WHERE d.dt BETWEEN '2004-12-22' AND '2004-12-28';

Was sollte daran nicht gehen?

Sascha Vetter

unread,
Jun 23, 2004, 10:58:26 AM6/23/04
to
Hallo Harald,

erstmal danke für deine schnelle Antwort!

> Naja, genau wie ich vorher gesagt habe, nur eben mit der ZimmerID mit drin:
>

> SELECT @dflt := uz stpreis AS dflt
> FROM u zimmer
> WHERE uz id = 1;
>
> SELECT sum (coalesce (r.up preis, @dflt)) AS sum
> FROM dates d
> LEFT JOIN u preise r ON r.up datum = d.dt AND r.up uzid = 1


> WHERE d.dt BETWEEN '2004-12-22' AND '2004-12-28';
>
> Was sollte daran nicht gehen?

Also ich musst dein Befehl wie folgt verändern dass er richtig
funktioniert:

SELECT @dflt := uz_stpreis AS dflt
FROM u_zimmer
WHERE uz_id = 1;

SELECT sum (coalesce (r.up_preis, @dflt)) AS sum

FROM u_preise d
LEFT JOIN u_preise r ON r.up_datum = d.up_datum AND r.up_uzid = 1
WHERE d.up_datum BETWEEN '2004-12-22' AND '2004-12-28' AND d.up_uzid =
1;

Dann bekomm ich aber nur die Summe der beiden betroffenen Tage
zusammenaddiert.

Daher ging meine Überlegung mal weiter, warum nicht einfach ein
count(*) mit abfragen und dann die Summe der Extratage und den Count
in Variablen einlesen und dann dank einer zweiten Abfrage, zusammen
mit der Zahl der insgesamten Tage des Aufenthalts (was ich leicht mit
übergeben kann) den Insgesamtpreis zu berechen, also so:

SELECT @exp_summe := sum (r.up_preis) AS sum, @exp_anzahl := count(*)
FROM u_preise d
LEFT JOIN u_preise r ON r.up_datum = d.up_datum AND r.up_uzid = 1
WHERE d.up_datum BETWEEN '2004-12-22' AND '2004-12-28' AND d.up_uzid =
1;

SELECT sum(uz_stpreis*(8-@exp_anzahl)+@exp_summe) AS gesamtpreis


FROM u_zimmer
WHERE uz_id = 1;

Dann bekomm ich leider ein Fehler dass angeblich die Zeile "@exp_summe
:= sum (r.up_preis) AS sum, @exp_anzahl := count(*)" was hat, das kann
aber nicht sein da der Befehl oben allein sauber läuft. Hätte ich
jetzt noch Zeit und müsste nicht dringent heim würde ich noch wenig
herumexperimentieren, so muss ich nun den Befehl unfertig stehen
lassen.

Was sehr schade wäre, wenn der Befehl funktionieren würde wäre dass
ich nicht für alle Zimmer den Insgesamtpreis bekomme sondern nur jedes
einzeln, könnte man da was machen, Harald?

Harald Fuchs

unread,
Jun 23, 2004, 11:44:00 AM6/23/04
to
In article <26654d80.04062...@posting.google.com>,
sav...@yahoo.de (Sascha Vetter) writes:

> Hallo Harald,
> erstmal danke für deine schnelle Antwort!

>> Naja, genau wie ich vorher gesagt habe, nur eben mit der ZimmerID mit drin:
>>
>> SELECT @dflt := uz stpreis AS dflt
>> FROM u zimmer
>> WHERE uz id = 1;
>>
>> SELECT sum (coalesce (r.up preis, @dflt)) AS sum
>> FROM dates d
>> LEFT JOIN u preise r ON r.up datum = d.dt AND r.up uzid = 1
>> WHERE d.dt BETWEEN '2004-12-22' AND '2004-12-28';
>>
>> Was sollte daran nicht gehen?

Das, was ich gepostet habe, hatte Unterstriche an den richtigen
Stellen (up_datum etc). Ich nehme an, Du verwendest einen kranken
Newsreader, der Postings willkürlich verändert.

> Also ich musst dein Befehl wie folgt verändern dass er richtig
> funktioniert:

> SELECT @dflt := uz_stpreis AS dflt
> FROM u_zimmer
> WHERE uz_id = 1;

> SELECT sum (coalesce (r.up_preis, @dflt)) AS sum
> FROM u_preise d
> LEFT JOIN u_preise r ON r.up_datum = d.up_datum AND r.up_uzid = 1
> WHERE d.up_datum BETWEEN '2004-12-22' AND '2004-12-28' AND d.up_uzid =
> 1;

Dann kann er aber nicht mehr funktionieren. Ich habe geschrieben, daß
Du eine Hilfstabelle (oben "dates" genannt) verwenden könntest, die
alle Tage in dem betreffenden Intervall enthält - egal, ob es dafür
Einträge in up_preise gibt oder nicht. Wenn Du diese Hilfstabelle
nochmal durch up_preise ersetzt, bekommst Du diese Tage auch nicht.

Sascha Vetter

unread,
Jun 24, 2004, 9:05:22 AM6/24/04
to
Hallo Harald,

> Das, was ich gepostet habe, hatte Unterstriche an den richtigen

> Stellen (up datum etc). Ich nehme an, Du verwendest einen kranken
> Newsreader, der Postings willk rlich ver ndert.
>

ich bin so schlimm, ich mach die ganze Sache über groups.google.de.

> > Also ich musst dein Befehl wie folgt ver ndern dass er richtig
> > funktioniert:
>

> > SELECT @dflt := uz stpreis AS dflt
> > FROM u zimmer
> > WHERE uz id = 1;
>
> > SELECT sum (coalesce (r.up preis, @dflt)) AS sum

> > FROM u preise d
> > LEFT JOIN u preise r ON r.up datum = d.up datum AND r.up uzid = 1
> > WHERE d.up datum BETWEEN '2004-12-22' AND '2004-12-28' AND d.up uzid =


> > 1;
>
> Dann kann er aber nicht mehr funktionieren. Ich habe geschrieben, da

> Du eine Hilfstabelle (oben "dates" genannt) verwenden k nntest, die
> alle Tage in dem betreffenden Intervall enth lt - egal, ob es daf r
> Eintr ge in up preise gibt oder nicht. Wenn Du diese Hilfstabelle
> nochmal durch up preise ersetzt, bekommst Du diese Tage auch nicht.

Logisch und stimmt natürlich, leider ist eine solche Hilfstabelle
nicht möglich. Also nun bin ich so weit:

SELECT @exp_summe:=sum(up_preis) AS sum, @exp_anzahl:=count(*)
FROM u_preise
WHERE up_datum BETWEEN '2004-12-22' AND '2004-12-28' AND up_uzid = 1;
SELECT (uz_stpreis*(8-@exp_anzahl))+@exp_summe AS gesamtpreis


FROM u_zimmer
WHERE uz_id = 1;

Somit bekomm ich den Gesamtpreis des Aufenthalts, leider aber nur von
einem Zimmer und es sind zwei Abfragen. Hätte jemand noch 'ne Idee wie
ich die Abfrage zusammenziehen kann (weniger wichtig) und es nicht für
ein Zimmer (uz_id = 1, up_uzid = 1) beschränken muss (sehr wichtig)?

Harald Fuchs

unread,
Jun 24, 2004, 11:28:39 AM6/24/04
to
In article <26654d80.04062...@posting.google.com>,
sav...@yahoo.de (Sascha Vetter) writes:

> Logisch und stimmt natürlich, leider ist eine solche Hilfstabelle
> nicht möglich.

Wieso denn nicht?

> Also nun bin ich so weit:

> SELECT @exp_summe:=sum(up_preis) AS sum, @exp_anzahl:=count(*)
> FROM u_preise
> WHERE up_datum BETWEEN '2004-12-22' AND '2004-12-28' AND up_uzid = 1;
> SELECT (uz_stpreis*(8-@exp_anzahl))+@exp_summe AS gesamtpreis
> FROM u_zimmer
> WHERE uz_id = 1;

> Somit bekomm ich den Gesamtpreis des Aufenthalts, leider aber nur von
> einem Zimmer und es sind zwei Abfragen. Hätte jemand noch 'ne Idee wie
> ich die Abfrage zusammenziehen kann (weniger wichtig) und es nicht für
> ein Zimmer (uz_id = 1, up_uzid = 1) beschränken muss (sehr wichtig)?

Was soll has heißen? Sieht der Gast mittendrin um oder was?

Sascha Vetter

unread,
Jun 25, 2004, 11:29:20 AM6/25/04
to
Also ich kam nun endlich auf eine saubere Lösung, danke Harald.

Für all die Groupsdurchsucher (zu denen ich mich normal zähle) hab ich
hier noch eine Zusammenfassung zum Abschauen und Lernen:

Also wir haben die Tabelle "u_zimmer" mit dem Standartpreis und der
ID:

CREATE TABLE `u_zimmer` (
`uz_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`uz_stpreis` INT UNSIGNED NOT NULL ,
PRIMARY KEY ( `uz_id` )
);

Da tragen wir zwei Einträge ein:

INSERT INTO `u_zimmer` ( `uz_stpreis` )
VALUES ('15');
INSERT INTO `u_zimmer` ( `uz_stpreis` )
VALUES ('20');

Dann noch die Tabelle für die Extrapreise mit einer ID, dem Datum für
den Extrapreis, der Extrapreis und dem Fremdschlüssel.

CREATE TABLE `u_preise` (
`up_id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`up_datum` DATE NOT NULL ,
`up_preis` INT NOT NULL ,
`up_uzid` INT UNSIGNED NOT NULL ,
PRIMARY KEY ( `up_id` )
);

OK - hier fügen wir folgende Werte hinzu:

INSERT INTO `u_preise` ( `up_datum` , `up_preis`, `up_uzid` )
VALUES ('2004-12-25', '20', '1');
INSERT INTO `u_preise` ( `up_datum` , `up_preis`, `up_uzid` )
VALUES ('2004-12-26', '20', '1');

Und mit folgende schöner Abfrage bekommen wir heraus welches Zimmer
wieviel über einen bestimmten Zeitraum kostet:

SELECT uz.uz_id, uz.uz_stpreis * ABS( TO_DAYS( '2004-12-28' ) -
TO_DAYS( '2004-12-22' ) ) + SUM( up.up_preis ) - COUNT( * ) *
uz.uz_stpreis AS gesamtpreis
FROM u_zimmer AS uz
LEFT JOIN u_preise AS up ON uz.uz_id = up.up_uzid AND up.up_datum
BETWEEN '2004-12-22' AND '2004-12-28'
GROUP BY uz.uz_id

Na allen dann noch ein schönes Wochenende!

Harald Fuchs

unread,
Jun 26, 2004, 7:54:08 AM6/26/04
to
In article <26654d80.04062...@posting.google.com>,
sav...@yahoo.de (Sascha Vetter) writes:

Ich verbringe das Wochenende in Zimmer 2, weil ich dort nichts
bezahlen muß. Deine Query ist zwar sehr elegant, hat aber ein paar Macken:

1. Bei der Tagesdifferenz mußt Du einen Tag dazuzählen.
2. sum (up_up_preis) ist NULL, wenn auch nur ein Wert NULL ist. NULLs
müssen auf 0 abgebildet werden.
3. count (*) sollte nur die Zeilen von u_preise zählen, die wirklich da
sind, und nicht die durch den LEFT JOIN gebildeten NULLs mitzählen.
Also stattdessen z.B. count (up.up_uzid).
4. Obwohl MySQL das Selektieren einer nicht aggregierten Zeile
erlaubt, die nicht im GROUP BY vorkommt, wäre es sauberer,
zusätzlich danach zu gruppieren. Das ändert nichts am Ergebnis
(weil bereits die erste Gruppenspalte eindeutig ist), entspricht
aber dem SQL-Standard.

Daraus ergibt sich:

SELECT uz.uz_id,
uz.uz_stpreis * (to_days ('2004-12-28') - to_days ('2004-12-22') + 1)
+ sum (coalesce (up.up_preis, 0))
- count (up.up_uzid) * uz.uz_stpreis AS gesamtpreis


FROM u_zimmer AS uz
LEFT JOIN u_preise AS up ON uz.uz_id = up.up_uzid
AND up.up_datum BETWEEN '2004-12-22' AND '2004-12-28'

GROUP BY uz.uz_id, uz.uz_stpreis;

Sascha Vetter

unread,
Jun 28, 2004, 9:44:20 AM6/28/04
to
Erstmal nochmal danke Harald, ich hab eigentlich gedacht die Abfrage
wäre vom Tisch und läuft schon wie oben geschrieben erfolgreich, aber
hab wohl nicht ausreichend getestet! Also ...

> Ich verbringe das Wochenende in Zimmer 2, weil ich dort nichts
> bezahlen muß.

Wenn dann auf meine Kosten, aber laut Abfrage kommt da einiges raus.

> Deine Query ist zwar sehr elegant, hat aber ein paar Macken:
>
> 1. Bei der Tagesdifferenz mußt Du einen Tag dazuzählen.

Muss ich mal nachrechnen, die Übernachtung kostet 20 Euro, ich will
mal vier Tage bleiben, sind aber nur drei Übernachtungen, d.h. vom
01.07.2004 bis 04.07.2004, keine Extrapreise vorhanden gibt die
Rechnung:

3*20 = 60 Euro

Die folgende Abfrage ergibt bei Zimmer 2:

SELECT uz.uz_id, uz.uz_stpreis * ABS( TO_DAYS( '2004-07-04' ) -
TO_DAYS( '2004-07-01' )) + SUM( up.up_preis ) - COUNT( * ) *


uz.uz_stpreis AS gesamtpreis
FROM u_zimmer AS uz
LEFT JOIN u_preise AS up ON uz.uz_id = up.up_uzid AND up.up_datum

BETWEEN '2004-07-01' AND '2004-07-04'
GROUP BY uz.uz_id

= 60, passt also.

Aber du hast nicht ganz unrecht, die Berechnung ist falsch wenn
Extratage dazukommen (dann nimmt er stehts ein Tag zuviel bei den
Extratagen, da 2004-07-04 zwischen '2004-07-01' und '2004-07-04'
liegt, laut where Abfrage. Ich will aber natürlich den Abreisetag
nicht zahlen) daher muss die Abfrage richtig lauten:

SELECT uz.uz_id, uz.uz_stpreis * (ABS( TO_DAYS( '2004-07-04' ) -
TO_DAYS( '2004-07-01' ))-COUNT( up.up_uzid )) + SUM( up.up_preis ) AS


gesamtpreis
FROM u_zimmer AS uz
LEFT JOIN u_preise AS up ON uz.uz_id = up.up_uzid AND up.up_datum

BETWEEN '2004-07-01' AND '2004-07-03'
GROUP BY uz.uz_id, uz.uz_stpreis;

Wie dir auffällt hab ich da einige Sache von unten schon mit
verändert, z.B. die COUNT ( up.up_uzid ) Geschichte.

> 2. sum (up_up_preis) ist NULL, wenn auch nur ein Wert NULL ist. NULLs
> müssen auf 0 abgebildet werden.

Ergibt bei mir keine Fehler, bzw. Veränderung.

> 3. count (*) sollte nur die Zeilen von u_preise zählen, die wirklich da
> sind, und nicht die durch den LEFT JOIN gebildeten NULLs mitzählen.
> Also stattdessen z.B. count (up.up_uzid).

Stimmt, siehe Abfrage oben, wurde geändert.

> 4. Obwohl MySQL das Selektieren einer nicht aggregierten Zeile
> erlaubt, die nicht im GROUP BY vorkommt, wäre es sauberer,
> zusätzlich danach zu gruppieren. Das ändert nichts am Ergebnis
> (weil bereits die erste Gruppenspalte eindeutig ist), entspricht
> aber dem SQL-Standard.

Wurde auch für den SQL-Standart geändert.

>
> Daraus ergibt sich:
>
> SELECT uz.uz_id,
> uz.uz_stpreis * (to_days ('2004-12-28') - to_days ('2004-12-22') + 1)
> + sum (coalesce (up.up_preis, 0))
> - count (up.up_uzid) * uz.uz_stpreis AS gesamtpreis
> FROM u_zimmer AS uz
> LEFT JOIN u_preise AS up ON uz.uz_id = up.up_uzid
> AND up.up_datum BETWEEN '2004-12-22' AND '2004-12-28'
> GROUP BY uz.uz_id, uz.uz_stpreis;

Bei mir läuft folgender Befehl sauber:

SELECT uz.uz_id, uz.uz_stpreis * (ABS( TO_DAYS( '2004-12-26' ) -
TO_DAYS( '2004-12-24' ))-COUNT( up.up_uzid )) + SUM( up.up_preis ) AS


gesamtpreis
FROM u_zimmer AS uz
LEFT JOIN u_preise AS up ON uz.uz_id = up.up_uzid

AND up.up_datum BETWEEN '2004-12-24' AND '2004-12-25'
GROUP BY uz.uz_id, uz.uz_stpreis;

Die coalesce Sache war bei mir nicht nötig da SUM( up.up_preis )
entweder 0 oder ein sinnvollen Wert ergibt.

0 new messages