kleinerheiner: mysql einfaches (oder auch nicht) abfrageproblem

guten morgen,

ich habe ein einfaches (oder auch nicht) abfrageproblem:

id|inhalt|auto_id
1|A|1
1|B|2
1|C|3
2|B|4
2|A|5

SELECT DISTINCT(id) FROM tabelle WHERE inhalt != "C"

die abfrage sollte "id" 2 ergeben, weil da kein "inhalt" C vorkommt. es wird aber auch "id" 1 ausgegeben. gibt es eine möglichkeit die abfrage entsprechend anders zu formulieren?

gruß
heiner

  1. guten morgen,

    ich habe ein einfaches (oder auch nicht) abfrageproblem:

    id|inhalt|auto_id
    1|A|1
    1|B|2
    1|C|3
    2|B|4
    2|A|5

    SELECT DISTINCT(id) FROM tabelle WHERE inhalt != "C"

    die abfrage sollte "id" 2 ergeben, weil da kein "inhalt" C vorkommt. es wird aber auch "id" 1 ausgegeben. gibt es eine möglichkeit die abfrage entsprechend anders zu formulieren?

    Moin Heiner,
    Wo ist Dein Problem?
    Bei der Ausgabe der Daten?

    Viele Grüße TomIRL

    1. moin TomIRL!

      meine abfrage liefert als ergebnis "id" 1 und 2. die abfrage muss irgendwie umgebaut werden, damit nur "id" 2 geliefert wird, weil nur bei "id" 2 kein C vorkommt.

      gruß
      heiner

      1. moin TomIRL!

        meine abfrage liefert als ergebnis "id" 1 und 2. die abfrage muss irgendwie umgebaut werden, damit nur "id" 2 geliefert wird, weil nur bei "id" 2 kein C vorkommt.

        Warte mal kleine Gedächtnisstütze:

        id|inhalt|auto_id
        1|A|1
        1|B|2
        1|C|3
        2|B|4
        2|A|

        $sql="SELECT *FROM tabellenname WHERE inhalt!='C' ORDER BY id";
        $zeilen = mysql_query($sql,....);
        if (!$zeilen) die("Anfrage war nicht erfolgreich");
        else

        while ($f = mysql_fetch_array($zeilen))
        {
           if ($f["id"]!=$id_old)
           {
            print ("$f[id] <br>");
             $id_old=$f["id"];
           }
        }

        Ich habs mal eben rausgerotzt!
        So wird jede ID genau nur einmal angezeigt.
        Willst Du jede jede mit Inhalt angezeiogt bekommen mußt Du die Abfrage  if ($f["id"]!=$id_old) rausnehmen und nur die Anzeige stehen lassen

        Viele Grüße aus Berlin

        TomIRL

        1. wenn du die abfrage

          SELECT DISTINCT(id) FROM tabelle WHERE inhalt != "C"

          benutzt, wird auch jede "id" nur einmal ausgeben (1,2). aber eben auch die id 1, die ein "C" enthält und nicht ausgegeben werden soll...

          oder reden wir aneinander vorbei?

          gruß
          heiner

          1. auch die id 1, die ein "C" enthält und nicht ausgegeben werden soll...

            Aha...

            oder reden wir aneinander vorbei?

            Also zum einen eine ID ist immer eindeutig.
            Das Bedeutet Deine Datenbankstruktur ist nicht gut.
            Du mütest die id in eine Tabelle auslegern.

            Die einzige Möglichkeit die ich sehe ohne die DB zu verändern ist folgende:

            • Zuerst die Datenabfragen welche c enthält.
            • Dann die ID die C entahlten in ein Array speichern
              Dann mittels foreach () das Array durchlaufen und nochmals abfragen mit einer zusätzllichen  WHERE Bedinmgung.
              Verstanden?

            TomIRL

            1. jo, das hab ich verstanden. wäre nur schön, wenn das problem in einer abfrage gelöst werden könnte.

              heiner

              1. jo, das hab ich verstanden. wäre nur schön, wenn das problem in einer abfrage gelöst werden könnte.

                Dann baue die DB um.
                TomIRL

                1. sowas hab ich befürchtet ;-)

                  1. yo,

                    sowas hab ich befürchtet ;-)

                    ruhig brauner. du hast eine eindeutigkeit in deiner tabelle, die namen sind nur unglücklich gewählt. musst also nichts umbauen.

                    Ilja

                    1. yo,

                      sowas hab ich befürchtet ;-)

                      ruhig brauner. du hast eine eindeutigkeit in deiner tabelle, die namen sind nur unglücklich gewählt. musst also nichts umbauen.

                      Naja dann mach doch mal einen Vorschlag.. wie man sein Problem mit einer Abfrage ohne Umbau lösen kann.
                      Er hat ziemlich eindeutig Redundanzen drin, die man selbstverständlich durch auslagern beseitigen könnte.
                      Ich hatte nicht geschrieben, dass er keine Eindeutigkeit hat, zumal ich glaube mich erinnern zu können, dass man selbst bei MySQL keine Tabellen anlegen kann ohne eine Primärschlüssel zu vergeben.

                      Viele Grüße aus Berlin
                      TomIRL

                      1. yo,

                        Naja dann mach doch mal einen Vorschlag.. wie man sein Problem mit einer Abfrage ohne Umbau lösen kann.

                        nicht auf die schnelle, da mysql keine unterabfragen mag.

                        Er hat ziemlich eindeutig Redundanzen drin, die man selbstverständlich durch auslagern beseitigen könnte.

                        redundanzen bedeutet nicht automatisch auslagern. wäre ja schlimm, wenn ich anfange jeden fremdschlüssel auszulagern.

                        Ich hatte nicht geschrieben, dass er keine Eindeutigkeit hat, zumal ich glaube mich erinnern zu können, dass man selbst bei MySQL keine Tabellen anlegen kann ohne eine Primärschlüssel zu vergeben.

                        wäre mir neu, dass man keine tabelle ohne primärschlüssel anlegen kann.

                        Ilja

                    2. hi ilja,

                      was meinst du mit: namen unglücklich gewählt?

                      gruß
                      heiner

                      1. yo heiner,

                        normalerweise ist die erste spalte der primärschlüssel einer tabelle, der die datensätze eindeutig identifiziert. auch nennt man diese spalte sehr oft id. bei dir ist es die dritte spalte und heisst auto_id oder so ähnlich. das ist syntaktisch richtig, nur eben ein wenig verwirrend. die erste spalte bei dir ist mehr eine art fremdschlüssel, auch wenn es keine andere tabelle gibt, aber vom sinn her

                        Ilja

                        1. hi ilja,

                          ja, ich weiss das die tabelle nicht das optimiale format hat. aber der "inhalt" kann extrem viele verschiedene werte annehmen, sodass eine syntax wie

                          id|A|B|C|D...(n=100.000)
                          1|0|2|1|0...

                          nicht möglich wäre. außerdem geht dabei die reihenfolge der inhalte verloren, bzw. ich müsste noch eine neue tabelle für die reihenfolge basteln.

                          mein problem könnte man wahrscheinlich mit unterabfragen lösen? mysql 4.1.1 kann das. dann muss ich das mal ausprobieren.

                          tom hatte ja den vorschlag gemacht: erst alle ids mit dem vorkommen von "C" herausfinden und dann alle anderen ids nehmen.

                          SELECT DISTINCT(id) FROM tabelle WHERE id NOT IN (SELECT DISTINCT(id) FROM tabelle WHERE inhalt = "C")

                          oder so ähnlich...

                          gruß
                          heiner

                          1. yo,

                            außerdem geht dabei die reihenfolge der inhalte verloren, bzw. ich müsste noch eine neue tabelle für die reihenfolge basteln.

                            alles was du tun solltest, um ein wenig mehr ordnung reinzubringen, wäre den namen der spalte id umzubenennen in zum beispiel gruppe und die auto spalte nach vorne zu verlagern und sie id nennen. das sind alles änderungen, welche die funktionalität nicht beinträchtigen, einfach durchzuführen sind und es etwas klarer gestalten.

                            mein problem könnte man wahrscheinlich mit unterabfragen lösen? mysql 4.1.1 kann das. dann muss ich das mal ausprobieren.

                            ja, unterabfragen ist ein weg, wobei es auch ohne geht. dann eben mit zwei getrennten abfragen, was eventuell performanter ist als eine unterabfrage.

                            tom hatte ja den vorschlag gemacht: erst alle ids mit dem vorkommen von "C" herausfinden und dann alle anderen ids nehmen.

                            genau so würde ich es auch machen. aber wie gesagt, sind unterabfragen hin nicht unbedinkt ratsam, das sie bei jedem durchlauf neu ausgeführt werden. wir brauchen diese liste der id's aber nur einmal. insofern bietet es sich an, zwei abfragen zu machen. die erste abfrage sucht die id (gruppen), die ein 'C' als Inhalt haben. wenn geht das gesamte ergebnis als string mit komma getrennt in einer variablen speichern. die zweite abfrage bezieht sich dann auf diese variablen in der WHERE klausel so wie ihr es mit der unterabfrage gemacht habt. WHERE id NOT IN ($variable)

                            Ilja

                            1. danke für den tipp, muss ich mal ausprobieren. ich hoffe die "id NOT IN ($variable)"-syntax läuft noch halbwegs schnell mit 100.000 id's drin.

                              sonst vielleicht eine temporäre tabelle anlegen...

                              mal gucken...

                              heiner

                              1. yo,

                                sonst vielleicht eine temporäre tabelle anlegen...

                                auch ein guter weg, auf jeden fall bei vielen datensätze unterabfragen vermeiden, wenn es geht.

                                Ilja