'Unlogisches' Verhalten in MySQL Statemant ;-)

norbert_pdm

Cadet 2nd Year
Registriert
März 2021
Beiträge
25
Hallo, hallo in die Runde,

ich hab ein etwas merkwürdiges Phänomen... Ich habe in einer Datenbank 3 Tabellen, welche ich mit folgenden (Teil-) Abfrage abfrage:

SQL:
SELECT
    ma.tbl_mitarbeiter_ID  as ma_ID,
    einzeln.tbl_doku_intern AS Intern
FROM
    tbl_doku_einzeln einzeln
    LEFT JOIN tbl_mitarbeiter_has_tbl_doku_einzeln dokueinzel ON dokueinzel.tbl_doku_einzeln_ID = einzeln.tbl_doku_einzeln_ID
    LEFT JOIN tbl_mitarbeiter ma ON dokueinzel.tbl_mitarbeiter_ID = ma.tbl_mitarbeiter_ID
WHERE
    IF (
        einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6',
        einzeln.tbl_doku_date = '2021-02-19'  AND ma.tbl_mitarbeiter_ID = '6'
    )

Wenn ich diese Abfrage ausführe, erhalte ich das gewünschte Ergebnis:
ma_IDDatumZeitIntern
62021-02-1912:45 - 14:151
62021-02-1913:00 - 15:00 NULL

Wenn ich die Abfrage jetzt so ergänze, dass ich den Zeitraum einengen will,
SQL:
SELECT
    ma.tbl_mitarbeiter_ID  as ma_ID,
    einzeln.tbl_doku_date AS Datum,
    CONCAT(DATE_FORMAT(einzeln.tbl_doku_starttime, '%H:%i'), ' - ', DATE_FORMAT(einzeln.tbl_doku_endtime, '%H:%i')) AS Zeit,
    einzeln.tbl_doku_intern AS Intern
FROM
    tbl_doku_einzeln einzeln
    LEFT JOIN tbl_mitarbeiter_has_tbl_doku_einzeln dokueinzel ON dokueinzel.tbl_doku_einzeln_ID = einzeln.tbl_doku_einzeln_ID
    LEFT JOIN tbl_mitarbeiter ma ON dokueinzel.tbl_mitarbeiter_ID = ma.tbl_mitarbeiter_ID
WHERE
    IF (
        einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6'
        AND (
           TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:50') - 1
        )
    )

erhalte ich:
ma_IDDatumZeitIntern
62021-02-1912:45 - 14:151

Was ich überhaupt nicht verstehe ist, warum die erste Zeile aus dem Result weg ist.
Mit Sicherheit hab ich da einen logischen Fehler, den ich nicht sehe.

Vielleicht hat ja jemand von euch eine Idee dazu.

Herzlichen Dank schon mal für Tipps,
Norbert
 
Wenn ich es richtig lese muss die Startzeit zwischen 10:00 und 12:50 liegen, 13:00 ist danach.
Und was meinst du mit "erste Zeile aus dem Result weg"? Die ist meiner Meinung nach noch da. Ich hätte gesagt, die zweite Zeile ist weg.
 
Es wird geprüft ob 13:00 zwischen 10:00 und 12:45 liegt. Da dies nicht so ist, wird die Zeile weggelassen. Es funktioniert genau so wie es dort steht.
 
tollertyp schrieb:
Wenn ich es richtig lese muss die Startzeit zwischen 10:00 und 12:50 liegen, 13:00 ist danach.
Und was meinst du mit "erste Zeile aus dem Result weg"? Die ist meiner Meinung nach noch da. Ich hätte gesagt, die zweite Zeile ist weg.
Du hast recht, die zweite Zeile ist weg... ;-)
Für mich ist das die 'erste' Zeile, weil sie meiner Meinung nach in der Fallunterscheidung zuerst abgeprüft wir...
Irgendwie steh ich völlig auf dem Schlauch...

Ich bastel das mal auseinander... Wenn ich das richtig sehe, ist es doch:
SQL:
IF (
    Bedingung,
    wenn wahr,
    wenn falsch
)

Auf meine Abfrage angewandt:
SQL:
IF (
    einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0',  // Prüft, ob NULL oder 0
    wenn die Bedingung wahr, dann hier,
    wenn falsch, dann hier                     // also bei 1
)



Der erste Teil (DANN) müsste also für den Fall dass itern = 0 oder NULL komplett ohne Zeitprüfung ausgegebene werden (im ersten Beispiel die zweite Zeile).
Der zweite Teil (SONST) müsste jetzt die Zeile prüfen, auf die diese Bedingungen (Datum und Zeit) zutreffen und diese ausgeben. Was er ja macht, da dort die Anfangszeit 12:45 ist...

Oder lieg ich komplett falsch?

VG; Norbert
 
Dann teste doch mal deine einzelnen Teile...

Was kommt denn dabei raus?

Code:
SELECT
    ma.tbl_mitarbeiter_ID  as ma_ID,
    einzeln.tbl_doku_date AS Datum,
    CONCAT(DATE_FORMAT(einzeln.tbl_doku_starttime, '%H:%i'), ' - ', DATE_FORMAT(einzeln.tbl_doku_endtime, '%H:%i')) AS Zeit,
    einzeln.tbl_doku_intern AS Intern
FROM
    tbl_doku_einzeln einzeln
    LEFT JOIN tbl_mitarbeiter_has_tbl_doku_einzeln dokueinzel ON dokueinzel.tbl_doku_einzeln_ID = einzeln.tbl_doku_einzeln_ID
    LEFT JOIN tbl_mitarbeiter ma ON dokueinzel.tbl_mitarbeiter_ID = ma.tbl_mitarbeiter_ID
WHERE
  einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0';

Ist da Zeile 2 im Ergebnis?


Das Abziehen von 1 am Ende , soll das eine Art Negation sein?
 
Code:
    IF (
        einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6'
        AND (
           TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:50') - 1
        )
    )

Markierte Zeile ist redundant und wird von der unteren Bedingung durch eine weitere Einschränkung obsolet.

EDIT: diese Zeile ist gemeint. --> einzeln.tbl_doku_date = '2021-02-19' AND ma.tbl_mitarbeiter_ID = '6',
 
tollertyp schrieb:
Vollzitat entfernt. Bitte Zitierregeln beachten: So zitiert man Teile eines Beitrags und vermeidet Fullquotes
Bei längerem Code bitte "@nutzername" verwenden.
Ich versteh es nicht....
Warum kommt da gar keine Zeile raus?
Ich hab so viele Zeilen mit NULL...

Das abziehen soll die Zeit um eine Sekunde verringern... Es ist kein Unterschied, ob man es mit oder ohne Klammern macht... ;-)

VG, Norbert
 
Zuletzt bearbeitet von einem Moderator:
@Aristotle:
Naja, der TE versucht umständlich folgendes zu sagen:

Ich verwende Java-Syntax:
a && (!b || c)

a = einzeln.tbl_doku_date = '2021-02-19' AND ma.tbl_mitarbeiter_ID = '6',
b = einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0'
c = TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:50') - 1

Seine Schreibweise ist eher
b ? a : a && c
Deshalb sehe ich das anders als du in Bezug auf die Redundanz.

Edit:
@norbert_pdm:
Ist vielleicht = Null die falsche Form der Abfrage? Muss es evtl "IS NULL" heißen? Keine Ahnung. Welche Datenbank hast du im Einsatz?

Und es ist immer besser, das Statement erst mal einfach runterzubrechen, um zu verstehen, was überhaupt passiert.
 
Vergiss das mit der Redundanz.

Das "= NULL" ist das Problem.

Was du aber machen könntest wäre den redundanten Teil rauszuziehen. Und ich finde das IF ziemlich hässlich und würde wohl eher das probieren:

Code:
WHERE
    (einzeln.tbl_doku_date = '2021-02-19' AND ma.tbl_mitarbeiter_ID = '6') AND
    ((einzeln.tbl_doku_intern IS NOT Null AND einzeln.tbl_doku_intern <> '0') OR
     (TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:50') - 1))

natürlich nicht getestet, nur von der Idee her...
 
tollertyp schrieb:
Vollzitat entfernt. Bitte Zitierregeln beachten: So zitiert man Teile eines Beitrags und vermeidet Fullquotes
Bei längerem Code bitte "@nutzername" verwenden.
Oh Man.... Du hast recht...
Mit IS NULL geht es sofort....

Ich hab schon ganz viel aus der WHERE Abfrage rausgeschmissen...
Aber wenn ihr noch ne Idee habt, dann gerne ... :-)

Die Vollständige Bedingung sieht so aus:

Code:
WHERE
  IF (
    einzeln.tbl_doku_intern = Null OR einzeln.tbl_doku_intern = '0',

    einzeln.tbl_doku_date = '2021-02-19'
    AND (
        TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:45') - 901
        OR
        TIME_TO_SEC(einzeln.tbl_doku_endtime) BETWEEN TIME_TO_SEC('10:00') + 901 AND TIME_TO_SEC('{12:45')
    )  
    AND ma.tbl_mitarbeiter_ID = '6',

    einzeln.tbl_doku_date = '2021-02-19'
    AND (
        TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:45') - 1
        OR
        TIME_TO_SEC(einzeln.tbl_doku_endtime) BETWEEN TIME_TO_SEC('10:00') + 1 AND TIME_TO_SEC('{12:45')
    )  
    AND ma.tbl_mitarbeiter_ID = '6'
)

Es sollen halt anhalt von intern verschiedene Rechnungen ausgeführt werden...

Danke!
VG, Norbert
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: tollertyp
Sehr gut. Mich würde aber trotzdem interessieren was du für ein Ergebnis erhälst wenn du disen Code ausführst.

Code:
SELECT
    ma.tbl_mitarbeiter_ID  as ma_ID,
    einzeln.tbl_doku_date AS Datum,
    CONCAT(DATE_FORMAT(einzeln.tbl_doku_starttime, '%H:%i'), ' - ', DATE_FORMAT(einzeln.tbl_doku_endtime, '%H:%i')) AS Zeit,
    einzeln.tbl_doku_intern AS Intern
FROM
    tbl_doku_einzeln einzeln
    LEFT JOIN tbl_mitarbeiter_has_tbl_doku_einzeln dokueinzel ON dokueinzel.tbl_doku_einzeln_ID = einzeln.tbl_doku_einzeln_ID
    LEFT JOIN tbl_mitarbeiter ma ON dokueinzel.tbl_mitarbeiter_ID = ma.tbl_mitarbeiter_ID
WHERE
    IF (
        einzeln.tbl_doku_intern IS NULL OR einzeln.tbl_doku_intern = '0',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6',
        einzeln.tbl_doku_date = '2021-02-19'  AND  ma.tbl_mitarbeiter_ID = '6'
        AND (
           TIME_TO_SEC(einzeln.tbl_doku_starttime) BETWEEN TIME_TO_SEC('10:00') AND TIME_TO_SEC('12:50') - 1
        )
    )
 
Aristotle schrieb:
Vollzitat entfernt. Bitte Zitierregeln beachten: So zitiert man Teile eines Beitrags und vermeidet Fullquotes
Bei längerem Code bitte "@nutzername" verwenden.
Das ist jetzt genau davon abhängig, wie 'intern' aussieht...
Ich erhalte jetzt bei beiden Varianten (also intern Null oder 1) das gleiche Ergebnis.
Das hab ich aus logischen Gründen so gewollt und es stellt ja nur einen kleinen Ausschnitt aus der ganzen Abfrage dar..

Ich zeig am einfachsten mal das Ergebnis:
Mit intern = 1
ma_IDDatumZeitIntern
62021-02-1912:45 - 14:151
62021-02-1913:00 - 15:00 NULL

Wenn ich jetzt in der entspreuchenden Zeile intern auf NULL setze, kommt:
ma_IDDatumZeitIntern
62021-02-1912:45 - 14:15 NULL
62021-02-1913:00 - 15:00 NULL

Das war für mich wichtig, um zu sehen, wie das gesamte Script arbeitet.
Die ganze WHERE Klausel ist weiter oben schon gepostet... :-)
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: Aristotle
Zurück
Oben