Vinzenz Mai: count aus mapping tabelle...

Beitrag lesen

Hallo Felix,

meine Ausführungen in diesem Beitrag sind vor allem dafür da, Dich beim Erlernen von SQL weiterzubringen.

die verknüpfung "where page_id=1 and page_id=2 group by visitor_id" funktioniert natürlich nicht, da ja pro zeile jeweils nur ein wert für die page existieren kann und das "and" daher nutzlos ist...

und schon merken wir, dass die Sprachlogik der gesprochenen Sprache "und" anders versteht, als die Sprachlogik einer Computersprache. Versuche es im Deutschen einmal mit "entweder"...

zwar könnte man im ersten Schritt OR verwenden, aber der IN-Operator ist hier deutlich besser geeignet. Nur reicht dies noch nicht ganz aus, wie Du meinem Beitrag entnehmen kannst.

Nehmen wir folgendes Beispiel

table_mapping:

mapping_id | page_id | visitor_id | created
----------------------------------------------
         1 |       1 |         2  | egal
         2 |       1 |         2  | auch
         3 |       2 |       111  | erst
         4 |       2 |        10  | recht
         5 |       2 |         2  | egal
         6 |       3 |        10  | auch
         7 |       1 |       111  | erst
         8 |       4 |        88  | recht
         9 |       3 |         2  | egal
        10 |       2 |        10  | auch

Durch scharfes Draufschauen sehen wir, dass die Benutzer mit der visitor_id 2 und 111 die Bedingung erfüllen, sowohl Seite 1 als auch Seite 2 angeschaut zu haben.

Die gewünschte Ergebismenge ist also

visitor_id
----------
        2
      111

Gehen wir nun so vor, wie ich vorgeschlagen habe (und was in Deinem Ansatz ebenfalls enthalten ist):

SELECT  
    page_id,  
    visitor_id  
FROM  
    table_mapping  
WHERE  
    page_id IN (1, 2)  

liefert:

page_id | visitor_id |
----------------------
      1 |         2  |
      1 |         2  |
      2 |       111  |
      2 |        10  |
      2 |         2  |
      1 |       111  |
      2 |        10  |

Du siehst, dass man noch nicht einfach zählen kann, weil der Benutzer 2 sich Seite 1 und der Benutzer 10 die Seite 2 zweimal angeschaut haben. Wir dürfen daher nur die *unterschiedlichen* Werte zählen und nutzen dazu die Aggregatsfunktion COUNT(DISTINCT), die zusammen mit einer Gruppierung mit der GROUP-BY-Klausel verwendet wird:

SELECT  
    visitor_id,  
    COUNT(DISTINCT page_id) Anzahl  
FROM  
    table_mapping  
WHERE  
    page_id IN (1, 2)  
GROUP BY  
    visitor_id  

[/code]
was uns

visitor_id | Anzahl
--------------------
         2 |     2
        10 |     1
       111 |     2

zurückliefert.

Nur diejenigen, die in der Spalte Anzahl eine 2 stehen haben, können beide Seiten (1 und 2) besucht haben. Deswegen können wir diese Ergebnismenge auf die Datensätze einschränken, bei denen Anzahl den Wert 2 aufweist. Anzahl ist das Ergebnis einer Aggregatsfunktion und eine Einschränkung kann deswegen erst nach Ermittlung aller Datensätze mit der HAVING-Klausel erfolgen - und nicht mit der WHERE-Klausel:

SELECT  
    visitor_id,  
    COUNT(DISTINCT visitor_id) Anzahl  
FROM  
    table_mapping  
WHERE  
    page_id IN (1, 2)  
GROUP BY  
    a.visitor_id  
HAVING  
    Anzahl = 2              -- in Standard-SQL darf man hier keinen Alias  
                            -- benutzen, [link:http://dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html@title=MySQL lässt es zu].  

und bekommen das oben geforderte Ergebnis:

visitor_id | Anzahl
--------------------
         2 |     2
       111 |     2

bzw. wenn wir die Anzahl nicht nutzen müssen (weil wir sie sowieso kennen):

SELECT  
    visitor_id  
FROM  
    table_mapping  
WHERE  
    page_id IN (1, 2)  
GROUP BY  
    a.visitor_id  
HAVING  
    COUNT(DISTINCT visitor_id) = 2  

mit der Ergebnistabelle:

visitor_id
-----------
         2
       111

Anmerkung:
MySQL sortiert wegen der GROUP-BY-Klausel implizit nach der Spalte visitor_id.

Dies ist *ein* möglicher Weg zum gewünschten Ziel und man erkennt leicht, wie man das Statement für weitere besuchte Seiten erweitern kann: Aufnahme in die Liste der Werte für IN und Erhöhen der notwendigen Anzahl bei HAVING.

Vermutlich hat Cheops eine vergleichbare Lösung in unserem Archiv gefunden, denn dieses Problem wurde hier in der Tat schon mehrfach behandelt. Schade, dass er den Beitrag, der ihm geholfen hat, nicht verlinkt hat.

Freundliche Grüße

Vinzenz