XOR in Kombination mit IS NULL

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • XOR in Kombination mit IS NULL

    Hallo,

    XOR liefert doch TRUE, wenn eines der beiden Argumente TRUE ist, oder nicht?

    Wenn ich also ein Anfrage mit "WHERE attr=10 XOR attr=11" formuliere, und attr ist 10 oder 11, dann wird die Zeile mit in das Ergebnis aufgenommen.


    Wieso liefert XOR kein TRUE wenn ich mit IS NULL auf ein Attribut prüfe?

    z.B. folgende Tabelle gegeben:
    Code:
    id  gegend_id  weg_id
    1     9         NULL
    Folgende Anfrage liefert kein Resultat:
    Code:
    SELECT * FROM `testxor`
    WHERE 
    (gegend_id=9 XOR gegend_id IS NULL) AND
    (weg_id=7777 XOR weg_id    IS NULL)
    Wenn ich aber das letzte XOR durch ein OR ersetze, dann wird die Zeile, die ich vorher auch schon erwartet hätte, zurückgegeben. Woran liegt das?

  • #2
    Wenn zB. gegend_id NULL ist, ergibt es NULL = 9 XOR NULL IS NULL. NULL = 9 ergibt NULL, NULL IS NULL ergibt TRUE. Und jetzt kommts:

    NULL XOR TRUE wird zu NULL
    NULL OR TRUE wird zu TRUE

    Ist bestimmt irgendwo im Handbuch dokumentiert, aber ich bin jetzt zu faul zum Suchen.

    Logische Erklärung für mich wäre:

    NULL ist weder TRUE noch FALSE, also kann es kein eindeutiges Ergebnis aus NULL XOR TRUE geben. Somit liefert MySQL einfach keinen Wert (NULL).
    Wohingegen <WERT> OR TRUE immer TRUE ist, es gibt keine andere Möglichkeit.
    Zuletzt geändert von h3ll; 22.08.2009, 17:00.

    Kommentar


    • #3
      Danke für die Erklärung, das leuchtet mir ein.

      Zitat von h3ll Beitrag anzeigen
      NULL XOR TRUE wird zu NULL
      Gibt es eine Möglichkeit, das NULL zu TRUE umzubiegen?

      Habe es eben mit einer IF-Konstruktion probiert, aber das wollte nicht so recht.

      Kommentar


      • #4
        (gegend_id IS NOT NULL AND gegend_id = 9) XOR gegend_id IS NULL

        Ich hoff aber, dass das nicht die tatsächliche abfrage ist, weil es so komplett unnötig aufgeblasen ist. Hier würde definitiv ein einfaches OR reichen.
        Zuletzt geändert von h3ll; 22.08.2009, 17:26.

        Kommentar


        • #5
          Den Unterschied zwischen
          (gegend_id IS NOT NULL AND gegend_id = 9) XOR gegend_id IS NULL
          und
          gegend_id = 9 XOR gegend_is IS NULL

          verstehe ich gerade nicht.

          Kannst du meine Frage bitte nochmal auf das SELECT aus dem Eingangspost beziehen?
          Zuletzt geändert von Boron; 22.08.2009, 17:49. Grund: doppelt verwirrt

          Kommentar


          • #6
            Warum willst du hier überhaupt XOR verwenden? Ein OR tuts doch genauso.

            Kommentar


            • #7
              Zitat von Boron Beitrag anzeigen
              Den Unterschied zwischen
              (gegend_id IS NOT NULL AND gegend_id = 9) XOR gegend_id IS NULL
              und
              gegend_id = 9 XOR gegend_is IS NULL

              verstehe ich gerade nicht.

              Kannst du meine Frage bitte nochmal auf das SELECT aus dem Eingangspost beziehen?
              Er hat NULL zu TRUE umgebogen, das wolltest du doch. Und in dem Beitrag wo du darum bittest, war der Bezug zum SELECT noch da.

              Kommentar


              • #8
                Zitat von h3ll Beitrag anzeigen
                Warum willst du hier überhaupt XOR verwenden? Ein OR tuts doch genauso.
                XOR und OR liefern unterschiedliche Ergebnisse.

                Code:
                CREATE TABLE `testxor` (
                  `id` smallint(5) unsigned NOT NULL auto_increment,
                  `gegend_id` int(11) unsigned default NULL,
                  `weg_id` int(11) unsigned default NULL,
                  PRIMARY KEY  (`id`)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=12 ;
                
                --
                -- Daten für Tabelle `testxor`
                --
                
                INSERT INTO `testxor` (`id`, `gegend_id`, `weg_id`) VALUES
                (1, 9, NULL),
                (6, 10, 12),
                (7, 10, 13),
                (8, 9, 16),
                (9, NULL, 17),
                (10, 5, NULL),
                (11, 10, NULL);
                Ein
                Code:
                SELECT * FROM `testxor` WHERE (gegend_id=10 XOR gegend_id IS NULL)
                gibt nur die Zeilen mit gegend_id = 10 zurück,

                während ein
                Code:
                SELECT * FROM `testxor` WHERE (gegend_id=10 OR gegend_id IS NULL)
                auch die mit NULL-befüllten Zeilen liefert.

                Mein Problem ist jetzt: Wenn die angegebene gegend_id nicht existiert, sollen halt alle Zeilen mit NULL-Werten zurückgegeben werden. Doch
                Code:
                SELECT * FROM `testxor` WHERE (gegend_id=77 XOR gegend_id IS NULL)
                tut das eben nicht. Obwohl NULL-Elemente für gegend_id existieren, bekomme ich ein leeres Resultat.

                Kommentar


                • #9
                  Zitat von Boron Beitrag anzeigen
                  Doch
                  Code:
                  SELECT * FROM `testxor` WHERE (gegend_id=77 XOR gegend_id IS NULL)
                  tut das eben nicht.
                  Wie soll es denn auch ...?

                  XOR verknüpft zwei Werte miteinander.
                  Hat deine Spalte gegend_id zwei Werte - in einem Datensatz? Natürlich nicht.

                  Völliger Humbug also, der komplette Ansatz.

                  Mein Problem ist jetzt: Wenn die angegebene gegend_id nicht existiert, sollen halt alle Zeilen mit NULL-Werten zurückgegeben werden.
                  Also willst du hier gar nicht die Inhaltes eines Datensatzes für sich genommen betrachten, sondern eine Betrachtung über mehrere Datensätze hinweg vornehmen.
                  Dafür sind JOINs das Mittel der Wahl - und kein Mangels Kenntnissen vollkommen blödsinnig angewandter logischer Operator XOR.
                  I don't believe in rebirth. Actually, I never did in my whole lives.

                  Kommentar


                  • #10
                    Bevor wir jetzt anfangen uns im Kreis zu drehen, drück ich mal auf Reset:
                    Du willst alles selektieren wo gegend_id einen bestimmten Wert (z.B. 9) hat oder NULL ist. Richtig?
                    Du hast es mit "WHERE gegend_id = 9 XOR gegend_id IS NULL" versucht. Das soll zutreffen, wenn das eine oder das andere wahr ist (OR), es soll aber nicht zutreffen, wenn beides wahr ist (das X in XOR).
                    Nun ist es aber so, dass die beiden Fälle 9 und NULL verschieden voneinander sind. Wenn eins davon wahr ist, kann das andere nicht wahr sein. Das heißt, das X in XOR ist immer erfüllt und deshalb genügt ein einfaches OR.

                    Nun spreche ich hier ganz salopp von "wahr". Aber das Statement gegend_id = 9 wird, wenn gegend_id den Wert NULL hat, nicht TRUE oder FALSE sondern NULL. Dreiwertige Logik.
                    h3ll hat 17:24 Uhr gezeigt, wie du dieses gegend_id = 9 === NULL zu einem gegend_id = 9 === TRUE casten kannst. Sozusagen. Da findet natürlich kein Cast in dem Sinne statt. Er hat das Statement gegend_id = 9 einfach so erweitert, dass es nicht mehr ausgewertet wird, wenn gegend_id NULL ist. Damit hat er den fehlerverursachenden Fall ausgeklammert. Das ändert an der gewünschten Semantik des gesamten Statement nichts, da in diesem Fall ohnehin der rechte Teil vom XOR wahr wird und somit das XOR erfüllt.

                    So, das war nun wahrscheinlich nicht sehr erhellend. Ist aber auch egal. Ich drück nochmal Reset, wir besinnen uns auf dein Anliegen (selektieren wenn NULL oder 9) und formulieren
                    WHERE gegend_id = 9 OR gegend_id IS NULL

                    Kommentar


                    • #11
                      Zitat von Boron Beitrag anzeigen
                      Ein
                      Code:
                      SELECT * FROM `testxor` WHERE (gegend_id=10 XOR gegend_id IS NULL)
                      gibt nur die Zeilen mit gegend_id = 10 zurück,

                      während ein
                      Code:
                      SELECT * FROM `testxor` WHERE (gegend_id=10 OR gegend_id IS NULL)
                      auch die mit NULL-befüllten Zeilen liefert.
                      Und warum nicht einfach:

                      WHERE gegend_id = 10

                      Gibt nur die Zeilen mit gegend_id = 10 zurück. Ist doch, was du willst, oder?

                      Ansonsten, wenn du Zeilen willst, wo gegend_id den Wert 10 oder NULL hat, dann so, wie onenerd geschrieben hat:

                      WHERE gegend_id = 10 OR gegend_id IS NULL

                      Wozu willst du da jetzt noch ein XOR reinbringen? Es sind doch beide Fälle ohne XOR abgedeckt.
                      Zuletzt geändert von h3ll; 22.08.2009, 19:56.

                      Kommentar


                      • #12
                        Zitat von onemorenerd Beitrag anzeigen
                        Du willst alles selektieren wo gegend_id einen bestimmten Wert (z.B. 9) hat oder NULL ist. Richtig?
                        Nein. Ich will alles selektieren, wo gegend_id = 9. Falls es KEIN Tupel dazu gibt, dann sollen mir alle Einträge, wo gegend_id NULL ist, zurückgegeben werden.

                        Kommentar


                        • #13
                          Also ich hab das so verstanden:
                          Wenn nach gegend_id 4711 gesucht wird (durch Nutzereingabe), die in den Daten nicht vorhanden ist - dann will er stattdessen als Suchergebnis alle Datensätze bekommen, in denen gegend_id NULL ist.

                          (Der total abwegige Ansatz mag natürlich für das Verständnis des eigentlichen Anliegens erschwerend sein ...)
                          I don't believe in rebirth. Actually, I never did in my whole lives.

                          Kommentar


                          • #14
                            Zitat von wahsaga Beitrag anzeigen
                            Also ich hab das so verstanden:
                            Wenn nach gegend_id 4711 gesucht wird (durch Nutzereingabe), die in den Daten nicht vorhanden ist - dann will er stattdessen als Suchergebnis alle Datensätze bekommen, in denen gegend_id NULL ist.
                            Genau

                            Kommentar


                            • #15
                              Eventuell so:

                              Code:
                              SELECT *
                              FROM tabelle
                              WHERE IF(
                                  ( SELECT COUNT(*) FROM tabelle WHERE gegend_id = 9 ) > 0,
                                  gegend_id = 9,
                                  gegend_id IS NULL
                              )
                              Aber wirklich zufrieden bin ich damit nicht.

                              Kommentar

                              Lädt...
                              X