MrSpoocy: MySQL - Left JOIN - Verbunde datensetze suchen (problem: doppel)

Hi, also ich habe eine Datenbank, die wie folgt aussieht:

CREATE TABLE IF NOT EXISTS `0815` (  
  `id` int(11) NOT NULL,  
  `zID` int(10) unsigned NOT NULL,  
  `Name` varchar(60) NOT NULL,  
  PRIMARY KEY  (`id`)  
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Daten:

INSERT INTO `0815` (`id`, `zID`, `Name`) VALUES  
(1, 123, 'Test'),  
(2, 123, 'Blub'),  
(3, 123, 'Keine Ahnung'),  
(4, 436, 'UserBlub'),  
(5, 436, 'Random Scheiß'),  
(6, 436, 'YX Scheiß ZP'),  
(7, 436, 'Weis ich nicht');  

Nun möchte ich eine Suche machen welche nach einem Namen sucht und alle einträge die die gleiche zID haben mit auflistet. Habs auch so mehr oder weniger hin bekommen:

SELECT T1.zID,T2.Name FROM `0815` AS T1  
LEFT JOIN `0815` AS T2 ON T2.zID = T1.zID  
WHERE T1.Name LIKE '%Blub%'

An sich geht es, an sich stimmt die auflistung nun:

zID  Name
123  Test
123  Blub
123  Keine Ahnung
436  UserBlub
436  Random Scheiß
436  YX Scheiß ZP
436  Weis ich nicht

Wenn ich ab nun nach "scheiß" suchen lassen dann (was auch logisch ist) listet er die zID 2 mal mit allen dazugehöriegen einträgen auf. Jemand eine
Idee das design oder die abfrage zu verbessern ?

  1. Hallo,

    SELECT T1.zID,T2.Name FROM 0815 AS T1

    LEFT JOIN 0815 AS T2 ON T2.zID = T1.zID
    WHERE T1.Name LIKE '%Blub%'

      
    warum verwendest Du einen [LEFT JOIN](http://aktuell.de.selfhtml.org/artikel/datenbanken/joins/#leftright_join)?  
    Warum verwendest Du keinen [INNER JOIN](http://aktuell.de.selfhtml.org/artikel/datenbanken/joins/#inner_join)?  
      
    
    > zID  Name  
    > 123  Test  
    > 123  Blub  
    > 123  Keine Ahnung  
    > 436  UserBlub  
    > 436  Random Scheiß  
    > 436  YX Scheiß ZP  
    > 436  Weis ich nicht  
      
    
    > Wenn ich ab nun nach "scheiß" suchen lassen dann (was auch logisch ist) listet er die zID 2 mal mit allen dazugehöriegen einträgen auf. Jemand eine  
    > Idee das design oder die abfrage zu verbessern ?  
      
    Ein paar Ideen:  
      
    - nutze DISTINCT  
    - gruppiere  
    - nutze Subselects statt des [Selfjoins](http://aktuell.de.selfhtml.org/artikel/datenbanken/fortgeschrittene-joins/selfjoin.htm).  
      
    Prüfe mit [EXPLAIN](http://dev.mysql.com/doc/refman/5.1/de/explain.html) den Aufwand der jeweiligen Lösung.  
      
      
    Freundliche Grüße  
      
    Vinzenz
    
    1. Hallo,

      SELECT T1.zID,T2.Name FROM 0815 AS T1

      LEFT JOIN 0815 AS T2 ON T2.zID = T1.zID
      WHERE T1.Name LIKE '%Blub%'

      
      >   
      > warum verwendest Du einen [LEFT JOIN](http://aktuell.de.selfhtml.org/artikel/datenbanken/joins/#leftright_join)?  
      > Warum verwendest Du keinen [INNER JOIN](http://aktuell.de.selfhtml.org/artikel/datenbanken/joins/#inner_join)?  
      >   
      > > zID  Name  
      > > 123  Test  
      > > 123  Blub  
      > > 123  Keine Ahnung  
      > > 436  UserBlub  
      > > 436  Random Scheiß  
      > > 436  YX Scheiß ZP  
      > > 436  Weis ich nicht  
      >   
      > > Wenn ich ab nun nach "scheiß" suchen lassen dann (was auch logisch ist) listet er die zID 2 mal mit allen dazugehöriegen einträgen auf. Jemand eine  
      > > Idee das design oder die abfrage zu verbessern ?  
      >   
      > Ein paar Ideen:  
      >   
      > - nutze DISTINCT  
      > - gruppiere  
      > - nutze Subselects statt des [Selfjoins](http://aktuell.de.selfhtml.org/artikel/datenbanken/fortgeschrittene-joins/selfjoin.htm).  
      >   
      > Prüfe mit [EXPLAIN](http://dev.mysql.com/doc/refman/5.1/de/explain.html) den Aufwand der jeweiligen Lösung.  
      >   
      >   
      > Freundliche Grüße  
      >   
      > Vinzenz  
        
        
      Hab jetzt mal so versucht:  
        
      `SELECT T2.* FROM `0815` AS T1,`0815` AS T2 WHERE T1.zID = T2.zID AND T1.Name LIKE '%Scheiß%' GROUP BY T2.id;`{:.language-sql}  
        
      Beim EXPLAIN ist der unterschied das hier "Using temporary; Using filesort" benutzt wird beim JOIN nicht. Bin mir jetzt nicht wirklich sicher was denn nun  
      von beidem besser ist :/
      
      1. Hallo,

        Ein paar Ideen:

        • nutze DISTINCT
        • gruppiere
        • nutze Subselects statt des Selfjoins.

        Hab jetzt mal so versucht:

        SELECT T2.* FROM 0815 AS T1,0815 AS T2 WHERE T1.zID = T2.zID AND T1.Name LIKE '%Scheiß%' GROUP BY T2.id;

        das ist immer noch ein Selfjoin, nur mit impliziter Joinsyntax, die anscheinend ...

        Beim EXPLAIN ist der unterschied das hier "Using temporary; Using filesort" benutzt wird beim JOIN nicht. Bin mir jetzt nicht wirklich sicher was denn nun
        von beidem besser ist :/

        ... zu überraschend deutlich schlechterer Performance führt.

        using temporary und using filesort findest Du auf der verlinkten Seite zu EXPLAIN weiter unten. Nutze die Suchfunktion, um die Abschnitte zu finden.

        Freundliche Grüße

        Vinzenz

  2. Hallo,

    zID  Name
    123  Test
    123  Blub
    123  Keine Ahnung
    436  UserBlub
    436  Random Scheiß
    436  YX Scheiß ZP
    436  Weis ich nicht

    Wenn ich ab nun nach "scheiß" suchen lassen dann (was auch logisch ist) listet er die zID 2 mal mit allen dazugehöriegen einträgen auf. Jemand eine
    Idee das design oder die abfrage zu verbessern ?

    Du hast ja auch 2 Datensätze, die "scheiß" beinhalten. Diese haben zufällig beide dieselbe zID. Ich hab keine Ahnung welcher Zweck sich hinter dieser zID verbirgt, das weisst nur du.

    Wenn du jetzt nur eimal jede eindeutige (Stichwort: Distinct) zID anzeigen lassen willst, kannst du das tun. Allerdings ohne Name und mittels DISTINCT oder einem GROUP BY zID. Wenn du den Spalte "Name" mit anzeigen willst, welche Inhalt soll es dir denn dann anzeigen, den vom ersten gefundenen, also "Random Scheiß" oder den vom zweiten gefundenen Datensatz "YX Scheiß ZP"? Kurz gesagt, das geht nicht "einfach so" ...

    Mit einer korrelierenden Unterabfrage könntest du dir z.b. den Namen

    • mit der geringsten Länge
    • der alphabetisch sortiert zuerst käme
    • der zuerst oder zuletzt eingetragenen
      ausgeben lassen.

    Was sollte dir ausgegeben werden und warum. Wenn du das "warum" weisst, kannst du es ggf auch in SQL umsetzen mit Aggregatsfunktionen wie MAX() oder MIN() oder sonstigen Möglichkeiten deines Datenbanksystems.

    Die Möglichkeit mit GROUP BY, die mySql dir bietet ist fachlich falsch.

    Ciao, Frank

    1. Was sollte dir ausgegeben werden und warum. Wenn du das "warum" weisst, kannst du es ggf auch in SQL umsetzen mit Aggregatsfunktionen wie MAX() oder MIN() oder sonstigen Möglichkeiten deines Datenbanksystems.

      Die Möglichkeit mit GROUP BY, die mySql dir bietet ist fachlich falsch.

      Ciao, Frank

      die zID ist eine art zugehörigkeit, also alle namen mit der gleichen zID sind 1 Person. Und bei der suche möchte ich alle namen finden die auf das eingegebene passen und dann dazu jewals alle namen die zu der Person gehören.