sebo: mehr als x mal

Hallo @ all

wie lasse ich mir bei mysql alle datensätze anzeigen wie mehr als 5 mal vorkommen?

  1. Hallo

    wie lasse ich mir bei mysql alle datensätze anzeigen wie mehr als 5 mal vorkommen?

    Es gibt die Aggregatsfunktion COUNT(). Nutze diese und eine geeignete WHERE-Klausel.
    Bitte beachte, dass Du nach allen Spalten gruppieren musst, auf die Du keine
    Aggregatsfunktion anwendest.

    Freundliche Grüße

    Vinzenz

    1. Glaub das ist etwas komplizierter!
      habe zwei tabellen:

      users:
      user_id|name|alter

      fotos:
      id|user_id|datum

      Ich will jetzt alle namen derjenigen haben, die mehr als 5 fotos haben.

      Wie du siehst eine ziemlich schwierige angelegenheit.

      1. Hi,

        überhaupt nicht bzw. nicht wirklich.

        Du musst die Tabellen erst zusammen-joinen und dann das COUNT/GROUP BY entsprechend auf die richtigen Felder anwenden

          
        SELECT a.user_id, a.name, a.alter, count(b.id) as zahl_fotos  
          FROM users as a  
          INNER JOIN fotos as b ON a.user_id = b.user_id  
          GROUP BY a.user_id, a.name, a.alter  
          HAVING zahl_fotos > 5  
        
        

        SQL-Code ohne Gewähr ...

        Gruss, Frank

        1. mist, dauert trotz INDEXE's auf id,user_id und name 133.03 Sekunden bei 430.212 rows

          1. Hallo,

            mist, dauert trotz INDEXE's auf id,user_id und name 133.03 Sekunden bei 430.212 rows

            Das ist viel zu viel. Was sagt EXPLAIN?

            Freundliche Grüße

            Vinzenz

            1.   
              mysql> EXPLAIN photos;  
              +-------------+-----------------------+------+-----+------------+----------------+  
              | Field       | Type                  | Null | Key | Default    | Extra          |  
              +-------------+-----------------------+------+-----+------------+----------------+  
              | id          | mediumint(8) unsigned |      | PRI | NULL       | auto_increment |  
              | description | text                  |      |     |            |                |  
              | data        | mediumblob            | YES  |     | NULL       |                |  
              | width       | int(4)                | YES  |     | NULL       |                |  
              | height      | int(4)                | YES  |     | NULL       |                |  
              | user_id     | mediumint(8) unsigned |      | MUL | 0          |                |  
              | datum   | date                  |      |     | 0000-00-00 |                |  
              +-------------+-----------------------+------+-----+------------+----------------+  
              7 rows in set (0.02 sec)  
              
              

              die users-tabelle hat nur ca 200 datensätze.

              1. Hallo

                mysql> EXPLAIN photos;

                nein, das ist nicht (so) wichtig oder interessant.
                Was sagt EXPLAIN zu Deiner Query, d.h. zu Franks oder meinem Vorschlag?

                Freundliche Grüße

                Vinzenz

                1. {code lang=sql]
                  mysql> EXPLAIN SELECT a.id, a.name, COUNT(b.id) AS count_files FROM users a INNER JOIN photos b ON a.id = b.user_id GROUP BY a.id, a.name HAVING COUNT(b.id) > 5;
                  +----+-------------+-------+------+---------------+------------+---------+------------+-------+---------------------------------+
                  | id | select_type | table | type | possible_keys | key        | key_len | ref        | rows  | Extra                           |
                  +----+-------------+-------+------+---------------+------------+---------+------------+-------+---------------------------------+
                  |  1 | SIMPLE      | a     | ALL  | PRIMARY       | NULL       |    NULL | NULL       | 20531 | Using temporary; Using filesort |
                  |  1 | SIMPLE      | b     | ref  | usernummer    | usernummer |       3 | users.a.id |     2 |                                 |
                  +----+-------------+-------+------+---------------+------------+---------+------------+-------+---------------------------------+
                  2 rows in set (0.00 sec)

                  [/code]

                2.   
                  mysql> EXPLAIN SELECT a.id, a.name, COUNT(b.id) AS count_files FROM users a INNER JOIN fotos b ON a.id = b.user_id GROUP BY a.id, a.name HAVING COUNT(b.id) > 5;  
                  +----+-------------+-------+------+---------------+------------+---------+------------+-------+---------------------------------+  
                  | id | select_type | table | type | possible_keys | key        | key_len | ref        | rows  | Extra                           |  
                  +----+-------------+-------+------+---------------+------------+---------+------------+-------+---------------------------------+  
                  |  1 | SIMPLE      | a     | ALL  | PRIMARY       | NULL       |    NULL | NULL       | 432221 | Using temporary; Using filesort |  
                  |  1 | SIMPLE      | b     | ref  | usernummer    | usernummer |       3 | users.a.id |     2 |                                 |  
                  +----+-------------+-------+------+---------------+------------+---------+------------+-------+---------------------------------+  
                  2 rows in set (0.00 sec)  
                    
                  
                  

                  ah sorry, hatte die original-tabelle versehendlich verwendet!

      2. Hallo

        Glaub das ist etwas komplizierter!

        aber nur ein wenig.

        users:
        user_id|name|alter

        fotos:
        id|user_id|datum

        Schließlich gibt es in SELFHTML Aktuell zwei Artikel zu JOINS, die ich Dir
        als Lektüre empfehle:

        Einführung in Joins
        Fortgeschrittene Jointechniken

        Ich will jetzt alle namen derjenigen haben, die mehr als 5 fotos haben.

        und natürlich auch den Benutzernamen dazu:

        Im ersten Schritt lassen wir uns alle Benutzer mit den zugehörigen id-Werten ihrer Bilder anzeigen:

        SELECT  
            users.name,  
            fotos.id  
        FROM  
            users  
        INNER JOIN fotos                  -- die beiden Tabellen sind durch die  
        ON users.user_id = fotos.user_id  -- Spalte user_id verknüpft  
        
        

        Nun zählen wir die Bilder, d.h. wieviele ids jedem Benutzer zugeordnet sind:

        SELECT  
            users.name,  
            COUNT(fotos.id) AS Anzahl  
        FROM  
            users  
        INNER JOIN fotos                  -- die beiden Tabellen sind durch die  
        ON users.user_id = fotos.user_id  -- Spalte user_id verknüpft  
        GROUP BY users.name               -- Zu jedem Namen gibt es eine Spalte  
        
        

        Aber: es könnte ja zwei Benutzer mit gleichem Namen geben:

        SELECT  
            users.id,  
            users.name,  
            COUNT(fotos.id) AS Anzahl  
        FROM  
            users  
        INNER JOIN fotos                  -- die beiden Tabellen sind durch die  
        ON users.user_id = fotos.user_id  -- Spalte user_id verknüpft  
        GROUP BY  
             users.id,                    -- gleichnamige Benutzer an der id  
                                          -- unterscheiden  
             users.name                   -- Zu jedem Namen gibt es eine Spalte  
        
        

        Nur die mit mehr als fünf Bildern, das erledigt die HAVING-Klausel, siehe
        in SELFHTML aktuell Datensätze gruppieren mit SQL:

        SELECT  
            users.id,  
            users.name,  
            COUNT(fotos.id) AS Anzahl  
        FROM  
            users  
        INNER JOIN fotos                  -- die beiden Tabellen sind durch die  
        ON users.user_id = fotos.user_id  -- Spalte user_id verknüpft  
        GROUP BY  
             users.id,                    -- gleichnamige Benutzer an der id  
                                          -- unterscheiden  
             users.name                   -- Zu jedem Namen gibt es eine Spalte  
        HAVING COUNT(fotos.id) > 5        -- nur solche mit mehr als fünf Bildern  
        
        

        Wie du siehst eine ziemlich schwierige angelegenheit.

        Wenn Du Dich damit eine Weile beschäftigst, findest Du heraus, dass das gar
        nicht so schwierig ist.

        Freundliche Grüße

        Vinzenz

        1. Das sind aber mehrere Statements! das hätte ich auch gekonnt ;)
          Wills gerne mit einem einzelnen!

          1. Hallo

            Das sind aber mehrere Statements! das hätte ich auch gekonnt ;)

            das war eine Schritt-für-Schritt-Anleitung, wie Du das Statement sukzessive
            erweiterst, um zum gewünschten Resultat zu gelangen. Hübsch einfach, Schritt
            für Schritt, damit Du das nachvollziehen - und so verstehen - kannst.

            Wills gerne mit einem einzelnen!

            Mein letztes Statement ist ein einzelnes Statement, es liefert das von Dir
            gewünschte und entspricht weitgehend Franks Vorschlag (kein Wunder):

            SELECT

            users.id,
                users.name,
                COUNT(fotos.id) AS Anzahl
            FROM
                users
            INNER JOIN fotos                  -- die beiden Tabellen sind durch die
            ON users.user_id = fotos.user_id  -- Spalte user_id verknüpft
            GROUP BY
                 users.id,                    -- gleichnamige Benutzer an der id
                                              -- unterscheiden
                 users.name                   -- Zu jedem Namen gibt es eine Spalte
            HAVING COUNT(fotos.id) > 5        -- nur solche mit mehr als fünf Bildern

              
            Du solltest Dir im Client Deiner Wahl, z.B. phpMyAdmin oder MySQL Query  
            Browser die einzelnen Statements der Reihe nach ausführen - und daraus lernen,  
            was sie tun. Du willst ja in Zukunft nicht bei jeder einfachen Abfrage hier  
            im Forum nachfragen müssen, oder?  
              
              
            Freundliche Grüße  
              
            Vinzenz
            
            1. Du verstehst das falsch: mit mehreren Statements kann ichs selbst auch!
              Der Beitrag zielt ausschließlich darauf ab, Kombinationsmöglichkeiten für ein einzelnes Statement zu finden wie hier auch schon geschehen.

              1. Hallo

                Du verstehst das falsch: mit mehreren Statements kann ichs selbst auch!

                Du verstehst mich falsch. Es gibt nur ein einziges Statement.

                Der Beitrag zielt ausschließlich darauf ab, Kombinationsmöglichkeiten für ein einzelnes Statement zu finden wie hier auch schon geschehen.

                Das hier ...

                SELECT

                users.id,
                    users.name,
                    COUNT(fotos.id) AS Anzahl
                FROM
                    users
                INNER JOIN fotos                  -- die beiden Tabellen sind durch die
                ON users.user_id = fotos.user_id  -- Spalte user_id verknüpft
                GROUP BY
                     users.id,                    -- gleichnamige Benutzer an der id
                                                  -- unterscheiden
                     users.name                   -- Zu jedem Namen gibt es eine Spalte
                HAVING COUNT(fotos.id) > 5        -- nur solche mit mehr als fünf Bildern

                  
                ... ist ein Statement. Eines, 1.  
                  
                  
                Freundliche Grüße  
                  
                Vinzenz
                
            2. Das Statement ist vom Aufbau her schon in etwa das was ich gesucht habe. Leider verlangsamt HAVING das ganze extrem stark. Kann man das vll. noch etwas anders lösen?
              Auch bei LIMIT 0,10 dauert die Abfrage noch ganze 20 Sekunden.

              1. Das Statement ist vom Aufbau her schon in etwa das was ich gesucht habe. Leider verlangsamt HAVING das ganze extrem stark. Kann man das vll. noch etwas anders lösen?
                Auch bei LIMIT 0,10 dauert die Abfrage noch ganze 20 Sekunden.

                HAVING verlangsamt um wieviel s? Wieviele Datensätze hast Du? Hast Du Indizes für die JOINs bzw. WHEREs gesetzt?

                1. werd keine doppelposts machen :)

              2. Hallo

                Das Statement ist vom Aufbau her schon in etwa das was ich gesucht habe. Leider verlangsamt HAVING das ganze extrem stark. Kann man das vll. noch etwas anders lösen?

                kannst Du bitte endlich EXPLAIN zur Abfrage befragen?
                Mit vernünftig eingesetzten Indexen kann das bei dieser bescheidenen Anzahl
                von Datensätzen nicht so lange dauern.

                Freundliche Grüße

                Vinzenz

                1. hab ich doch schon längst (siehe unten)

                  1. Hallo,

                    wie schnell ist ein einfaches

                      
                    SELECT user_id, count(*)  
                      FROM fotos  
                      GROUP BY user_id  
                    
                    

                    Schritt 2: um wieviel langsamer ist

                      
                    SELECT user_id, count(*)  
                      FROM fotos  
                      GROUP BY user_id  
                      HAVING count(*) > 5  
                    
                    

                    Wenn du einen Index auf user_id hast und es nur ca. 2500 user_ids gibt, dann ist der Suchradius auch auf etwa diese 2500 user_ids beschränkt und das sollte rasant schanell gehen.

                    Grüsse, Frank

                    1. Hallo Frank,

                      Hallo,

                      wie schnell ist ein einfaches

                      SELECT user_id, count(*)
                        FROM fotos
                        GROUP BY user_id

                        
                      Version A:  
                      ~~~sql
                      SELECT  
                          u.user_id,  
                          u.name,  
                          f.anzahl  
                      FROM users u  
                      INNER JOIN (  
                          SELECT  
                              user_id,  
                              COUNT(user_id) AS anzahl  
                          FROM fotos  
                          GROUP BY user_id  
                          HAVING anzahl > 5  
                      ) f  
                      ON u.user_id = f.user_id
                      

                      war bei mir (nicht unerwartet) deutlich schneller als

                      Version B:

                      SELECT  
                          u.user_id,  
                          u.name,  
                          COUNT(f.id) AS anzahl  
                      FROM users u  
                      INNER JOIN fotos f  
                      ON u.user_id = f.user_id  
                      GROUP BY  
                          u.user_id,  
                          u.name  
                      HAVING anzahl > 5
                      

                      Testdaten: 200 User, alle über 5 Fotos, 500.000 Fotos
                      Ausführungszeiten im Bereich von 2 Sekunden (A) zu 0,3 Sekunden (B).

                      Freundliche Grüße

                      Vinzenz

  2. Hi,
    join ist was du suchst.

    Beispiel findest du unterhalb im folgenden Link:
    http://de.wikipedia.org/wiki/SQL

    Gruss
    Denise

    1. das wusste ich bereits. Leider reicht join nicht ansatzweise ;)