Hallo,
um diese Zeit sollte ich keine Beiträge mehr schreiben. Der Weg ist in Ordnung, die Statements sind es nicht, einer Optimierung und C&P sei Dank.
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
[...] richtiges gestrichen.
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 page_id) Anzahl -- wir zählen unterschiedliche page_ids
-- nicht visitor_ids
FROM
table_mapping
WHERE
page_id IN (1, 2)
GROUP BY
visitor_id -- Tabellenalias entfernt
-- vorher war's komplizierter
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 | 2bzw. 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
visitor_id -- Tabellenalias entfernt
HAVING
COUNT(DISTINCT page_id) = 2 -- richtige Spalte gezählt
mit der Ergebnistabelle:
visitor_id
2
111
Code (copy & paste)-getestet mit MySQL 5.1.41 und MS SQL-Server 2005. Letzterer meckert (korrekt) erstes Statement mit dem Spaltenalias an, so wie es in meinem Kommentar steht ...
Freundliche Grüße
Vinzenz