Peter Thomassen: Zwei Queries ... äquivalent?

Hallo!

Ich habe hier zwei verschiedene Queries:

SELECT number, COUNT(contract.id\_contact-signatory) as anz FROM contact
 LEFT JOIN contract ON (contact.id = contract.id\_contact-signatory)
 GROUP BY number HAVING anz = 0

SELECT number FROM contact
 WHERE id NOT IN(SELECT id\_contact-signatory FROM contract)

Die erste funktioniert und liefert mir alle Kundennummern, für die kein Vertrag existiert. Die zweite wollte nach meinem Dafürhalten äquivalent zur ersten sein - und liefert mir ein leeres Resultset.

Lasse ich das NOT weg, so bekomme ich alle Kundennummern, für die ein Vertrag existiert - so grundsützlich fasch kann die Query also nicht sein. Woran liegt's?

Ich hab nicht viel Erfahrung mit Subqueries, also meldet euch bitte auch, wenn ihr der Meinung seid, dass es so eigentlich gehen müsste, damit ich wenigstens da auf der sicheren Seite bin. Danke!

Peter

  1. Hallo

    SELECT number FROM contact
     WHERE NOT id IN(SELECT id\_contact-signatory FROM contract)

    sollte gehen.

    Gruss,
    Daniel

  2. Hallo Peter Thomassen,

    SELECT number, COUNT(contract.id\_contact-signatory) as anz FROM contact
    LEFT JOIN contract ON (contact.id = contract.id\_contact-signatory)
    GROUP BY number HAVING anz = 0

    Meiner Meinung nach besser:

    SELECT DISTINCT number
    FROM contact
    LEFT JOIN contract
    ON contact.id = contract.id\_contact-signatory
    WHERE contract.id\_contact-signatory IS NULL

    SELECT number FROM contact
    WHERE id NOT IN(SELECT id\_contact-signatory FROM contract)

    nicht mit NOT IN, sondern <> ANY

    SELECT number
    FROM contact
    WHERE id <> ANY (SELECT id\_contact-signatory FROM contract)
    http://dev.mysql.com/doc/mysql/en/ANY_IN_SOME_subqueries.html

    NOT EXISTS dürfte auch eine Möglichkeit sein.

    Die erste funktioniert und liefert mir alle Kundennummern, für die kein Vertrag existiert. Die zweite wollte nach meinem Dafürhalten äquivalent zur ersten sein - und liefert mir ein leeres Resultset.

    Du kannst auf die COUNT-Funktion und die GROUP-BY-Klausel verzichten :-)

    Ich hab nicht viel Erfahrung mit Subqueries, also meldet euch bitte auch, wenn ihr der Meinung seid, dass es so eigentlich gehen müsste, damit ich wenigstens da auf der sicheren Seite bin. Danke!

    In sehr vielen Fällen sind Subqueries ineffizient. Dieses ist ein schönes Beispiel dafür.

    Freundliche Grüsse,

    Vinzenz

    1. Hallo Vinzenz!

      Meiner Meinung nach besser:

      SELECT DISTINCT number
      FROM contact
      LEFT JOIN contract
      ON contact.id = contract.id\_contact-signatory
      WHERE contract.id\_contact-signatory IS NULL

      Danke.

      SELECT number FROM contact
      WHERE id NOT IN(SELECT id\_contact-signatory FROM contract)

      nicht mit NOT IN, sondern <> ANY

      SELECT number
      FROM contact
      WHERE id <> ANY (SELECT id\_contact-signatory FROM contract)
      http://dev.mysql.com/doc/mysql/en/ANY_IN_SOME_subqueries.html

      Meint, dass id ungleich irgendeinem id_contact-signatory sein muss. Das ist wahr --> Selbes Ergebnis wie bei SELECT number FROM contact.

      NOT EXISTS dürfte auch eine Möglichkeit sein.

      Wie geht das dann?

      In sehr vielen Fällen sind Subqueries ineffizient. Dieses ist ein schönes Beispiel dafür.

      Warum?

      Bye,
      Peter

      1. Hi,

        In sehr vielen Fällen sind Subqueries ineffizient. Dieses ist ein schönes Beispiel dafür.

        Warum?

        EXPLAIN SELECT ...

        Cheatah

        --
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. Hallo,

          In sehr vielen Fällen sind Subqueries ineffizient. Dieses ist ein schönes Beispiel dafür.

          Warum?

          EXPLAIN SELECT ...

          Bitte verzeih mir, ich will hier keinen nerven oder rumtrollen ... aber mir sagt das echt nix. Beim Join sind die beiden Selects SIMPLE, beim Subselect der eine PRIMARY und der andere eine DEPENDENT SUBQUERY, Join verwendet als Extra "where", "temporary" und "distinct"; Subselect zweimal "where". Sonst gibt es keine Unterschiede.

          Woraus kann ich jetzt schließen, dass der Subselect ineffizient ist?

          Bye,
          Peter

    2. Hallo Vinzenz,

      SELECT number FROM contact
      WHERE id NOT IN(SELECT id\_contact-signatory FROM contract)

      nicht mit NOT IN, sondern <> ANY

      Klappt irgendwie nicht, kann den Fehler nicht finden ... mich nachgebauten, gleich strukturierten Tabellen funktioniert's. Naja, das bekomm ich schon noch irgndwie hin ...

      Übrigens: "Use NOT (a = ANY (...)) rather than a <> ALL (...)." (http://dev.mysql.com/doc/mysql/en/Optimising_subqueries.html)

      In sehr vielen Fällen sind Subqueries ineffizient. Dieses ist ein schönes Beispiel dafür.

      "Replace a join with a subquery. For example, use this query:

      SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
        SELECT column1 FROM t2);

      Instead of this query:

      SELECT DISTINCT t1.column1 FROM t1, t2
        WHERE t1.column1 = t2.column1;"

      Ebenfalls http://dev.mysql.com/doc/mysql/en/Optimising_subqueries.html.

      Ich bin neugierig, was nun richtig ist.

      Bye,
      Peter

      1. Hallo Peter Thomassen,

        "Replace a join with a subquery. For example, use this query:

        ...

        Ebenfalls http://dev.mysql.com/doc/mysql/en/Optimising_subqueries.html.

        These tricks might cause programs to go faster or slower. Using MySQL facilities like the BENCHMARK() function, you can get an idea about what helps in your own situation.

        Gleiche Quelle :-)

        Freundliche Grüsse,

        Vinzenz

        1. Tach,

          "Replace a join with a subquery. For example, use this query:

          ...

          Ebenfalls http://dev.mysql.com/doc/mysql/en/Optimising_subqueries.html.

          These tricks might cause programs to go faster or slower. Using MySQL facilities like the BENCHMARK() function, you can get an idea about what helps in your own situation.

          Hm... warum steht das unter "Optimising Subquerise"? :-)

          Grüße aus Würzburg,
          Peter

  3. Hi,

    SELECT number, COUNT(contract.id\_contact-signatory) as anz FROM contact
    SELECT number FROM contact
    Die erste funktioniert und liefert mir alle Kundennummern, für die kein Vertrag existiert. Die zweite wollte nach meinem Dafürhalten äquivalent zur ersten sein - und liefert mir ein leeres Resultset.

    Nein, die beiden Queries sind keinesfalls Ergebnis-identisch. Die erste liefert zwei Spalten, die zweite nur eine.

    cu,
    Andreas

    --
    MudGuard? Siehe http://www.Mud-Guard.de/
    Fachfragen per E-Mail halte ich für unverschämt und werde entsprechende E-Mails nicht beantworten. Für Fachfragen ist das Forum da.
    1. Hallo MudGuard,

      SELECT number, COUNT(contract.id\_contact-signatory) as anz FROM contact
      SELECT number FROM contact
      Die erste funktioniert und liefert mir alle Kundennummern, für die kein Vertrag existiert. Die zweite wollte nach meinem Dafürhalten äquivalent zur ersten sein - und liefert mir ein leeres Resultset.

      Nein, die beiden Queries sind keinesfalls Ergebnis-identisch. Die erste liefert zwei Spalten, die zweite nur eine.

      Mh ja, das wusste ich :-) Ich meinte den Inhalt der ersten Spalte. Aber Du hast schon recht.

      Bye,
      Peter