COUNT(DISTINCT column) zählt, wie viele verschiedene Werte eine Spalte enthält: Ein Wert, der zehnmal vorkommt, zählt einmal, und NULLs zählen gar nicht. Die Beispiele funktionieren in PostgreSQL, MySQL, SQLite und SQL Server.
So verwendest du COUNT DISTINCT
Setz DISTINCT in COUNT(), vor die Spalte oder den Ausdruck, den du zählen willst:
COUNT(DISTINCT expression)
Am besten verstehst du es im Vergleich mit den beiden anderen Formen von COUNT. COUNT(*) zählt Zeilen, COUNT(column) zählt Zeilen, in denen die Spalte nicht NULL ist, und COUNT(DISTINCT column) zählt die verschiedenen Werte, die nicht NULL sind:
-- Input: orders
-- order_id | customer_id
-- ---------+------------
-- 1 | 1042
-- 2 | 1077
-- 3 | 1042
-- 4 | NULL
SELECT COUNT(*) AS all_rows,
COUNT(customer_id) AS with_customer,
COUNT(DISTINCT customer_id) AS customers
FROM orders;
-- Output:
-- all_rows | with_customer | customers
-- ---------+---------------+----------
-- 4 | 3 | 2
Vier Bestellungen kamen von zwei Kunden: 1042 hat zweimal bestellt, und Bestellung 4 hat gar keinen Kunden.
Wichtige Regeln
- NULLs werden nicht gezählt. Wenn ein fehlender Wert als ein weiterer zählen soll, addier ihn selbst:
-- Input: the orders table above
SELECT COUNT(DISTINCT customer_id)
+ MAX(CASE WHEN customer_id IS NULL THEN 1 ELSE 0 END) AS customers_and_guests
FROM orders;
-- Output: 3
-
MySQL und SQL Server ignorieren standardmäßig Groß- und Kleinschreibung, zählen
'SQL'und'sql'also als einen Wert. ZählLOWER(tag), wenn die Schreibweise keine Rolle spielen soll:
-- Input: tags
-- post_id | tag
-- --------+---------
-- 1 | SQL
-- 2 | sql
-- 3 | Postgres
SELECT COUNT(DISTINCT tag) FROM tags;
-- Output: 3 (2 in MySQL and SQL Server)
SELECT COUNT(DISTINCT LOWER(tag)) FROM tags;
-- Output: 2
-
DISTINCT funktioniert auch in
SUMundAVG, entfernt aber doppelte Werte, nicht doppelte Zeilen. Zwei verschiedene Produkte mit demselben Preis werden nur einmal addiert:
-- Input: order_lines
-- product | price
-- ---------+------
-- Pen | 2.00
-- Pencil | 2.00
-- Notebook | 5.00
SELECT SUM(price) AS total, SUM(DISTINCT price) AS distinct_total FROM order_lines;
-- Output:
-- total | distinct_total
-- ------+---------------
-- 9.00 | 7.00
Alternative Syntax
COUNT(DISTINCT ...) nimmt eine Spalte. Um die verschiedenen Kombinationen mehrerer Spalten zu zählen, zählst du die Zeilen einer DISTINCT-Subquery. PostgreSQL und MySQL haben dafür auch Kurzformen:
-- Input: orders
-- order_id | customer_id | product_id
-- ---------+-------------+-----------
-- 1 | 1 | 23
-- 2 | 12 | 3
-- 3 | 1 | 23
-- 4 | 12 | 5
SELECT COUNT(*) FROM (SELECT DISTINCT customer_id, product_id FROM orders) AS pairs;
-- Output: 3
-- PostgreSQL
SELECT COUNT(DISTINCT (customer_id, product_id)) FROM orders;
-- Output: 3
-- MySQL
SELECT COUNT(DISTINCT customer_id, product_id) FROM orders;
-- Output: 3
Manchmal siehst du auch, dass die Spalten mit CONCAT() zu einem String zusammengeklebt werden. Das braucht ein Trennzeichen: Ohne eins werden Kunde 1 mit Produkt 23 und Kunde 12 mit Produkt 3 beide zu '123':
-- Input: the orders table above
SELECT COUNT(DISTINCT CONCAT(customer_id, product_id)) FROM orders;
-- Output: 2
SELECT COUNT(DISTINCT CONCAT(customer_id, '_', product_id)) FROM orders;
-- Output: 3
Eine exakte Distinct-Zählung muss jeden Wert sortieren oder hashen, was bei sehr großen Tabellen langsam wird. SQL Server hat APPROX_COUNT_DISTINCT(), das schneller ist und in 97 % der Fälle höchstens 2 % vom exakten Wert abweicht:
-- SQL Server
-- Input: the orders table above
SELECT APPROX_COUNT_DISTINCT(customer_id) AS customers FROM orders;
-- Output: 2
Wann solltest du COUNT DISTINCT verwenden?
Nimm COUNT DISTINCT, wenn die Frage „Wie viele verschiedene …?“ lautet und nicht „Wie viele Zeilen?“. Die meisten dieser Fragen fallen in eine dieser vier Kategorien.
Eindeutige Besucher, Kunden oder Produkte zählen
Ein Log von Besuchen, Bestellungen oder Verkäufen erfasst denselben Besucher, Kunden oder dasselbe Produkt immer wieder. COUNT DISTINCT auf die ID macht aus diesen Zeilen eine Kopfzahl.
Eindeutige Werte pro Gruppe zählen
Mit GROUP BY bekommst du eine Distinct-Zählung pro Gruppe: verschiedene Studierende pro Kurs, verschiedene Produkte pro Anbieter, verschiedene Kunden pro Monat.
Eindeutige Spaltenkombinationen zählen
Manchmal sind zwei Zeilen nur dann „gleich“, wenn zwei Spalten übereinstimmen: derselbe User mit derselben Art von Problem oder dieselbe Route zwischen zwei Flughäfen. Zähl die Kombinationen mit einer der mehrspaltigen Formen aus „Alternative Syntax“.
Eindeutige Werte mit Bedingung zählen
Setz einen CASE-Ausdruck in COUNT(DISTINCT ...), um nur bestimmte Zeilen zu zählen. Das CASE liefert NULL für die Zeilen, die du nicht willst, und NULLs werden nicht gezählt – so kann eine Abfrage mehrere gefilterte Zählungen nebeneinander liefern.
Praxisbeispiele für COUNT DISTINCT
Monatlich aktive User
Zähl die User, die im September irgendetwas gemacht haben, egal wie oft sie wiederkamen:
-- Input: events
-- event_id | user_id | event_date
-- ---------+---------+-----------
-- 1 | 301 | 2026-08-30
-- 2 | 302 | 2026-09-02
-- 3 | 302 | 2026-09-15
-- 4 | 305 | 2026-09-21
-- 5 | 302 | 2026-10-01
SELECT COUNT(DISTINCT user_id) AS active_users
FROM events
WHERE event_date >= '2026-09-01' AND event_date < '2026-10-01';
-- Output: 2
Verkaufte Produkte pro Anbieter
COUNT(*) liefert die Anzahl der Verkäufe jedes Anbieters und COUNT(DISTINCT product), wie viele verschiedene Produkte diese Verkäufe umfassten:
-- Input: sales
-- vendor | product | color
-- -----------+----------+------
-- Acme | Mug | Red
-- Acme | Mug | Blue
-- Acme | Mug | Red
-- Acme | Tote Bag | Red
-- Brightside | Notebook | Black
SELECT vendor, COUNT(*) AS sales, COUNT(DISTINCT product) AS products
FROM sales
GROUP BY vendor;
-- Output:
-- vendor | sales | products
-- -----------+-------+---------
-- Acme | 4 | 2
-- Brightside | 1 | 1
Routen einer Airline
Eine Route besteht aus Start und Ziel zusammen. Zwei Flüge von LHR nach JFK sind eine Route, aber JFK nach LHR ist eine andere:
-- Input: flights
-- flight_no | origin | destination
-- ----------+--------+------------
-- 101 | LHR | JFK
-- 105 | LHR | JFK
-- 102 | JFK | LHR
-- 301 | LHR | LAX
SELECT COUNT(*) AS routes
FROM (SELECT DISTINCT origin, destination FROM flights) AS r;
-- Output: 3
Kunden nach Preis ihrer Käufe
Zähl die Kunden, die Produkte 100 bis 200 gekauft haben, und teil sie dann nach dem Preis ihrer Bestellungen auf. Kunde 7 hat zwei günstige Bestellungen aufgegeben, zählt aber einmal, und das Produkt von Kunde 15 liegt außerhalb des Bereichs:
-- Input: orders
-- order_id | customer_id | product_id | price
-- ---------+-------------+------------+-------
-- 1 | 7 | 105 | 25.00
-- 2 | 7 | 142 | 40.00
-- 3 | 9 | 150 | 120.00
-- 4 | 12 | 188 | 310.00
-- 5 | 15 | 260 | 30.00
SELECT
COUNT(DISTINCT customer_id) AS customers,
COUNT(DISTINCT CASE WHEN price BETWEEN 1 AND 50 THEN customer_id END) AS low_spenders,
COUNT(DISTINCT CASE WHEN price BETWEEN 51 AND 150 THEN customer_id END) AS mid_spenders,
COUNT(DISTINCT CASE WHEN price > 150 THEN customer_id END) AS high_spenders
FROM orders
WHERE product_id BETWEEN 100 AND 200;
-- Output:
-- customers | low_spenders | mid_spenders | high_spenders
-- ----------+--------------+--------------+--------------
-- 3 | 1 | 1 | 1
Ein Kunde mit Bestellungen in zwei Preisklassen wird in beiden gezählt.
Mehr zu COUNT DISTINCT
In diesem Blog:
-
SQL GROUP BY Guide:
COUNT,SUMundAVGpro Gruppe - Duplikate finden in SQL: Werte finden, die mehr als einmal vorkommen
- Duplikate entfernen in SQL: überzählige Kopien löschen
- SQL CASE Guide: die Bedingungen hinter bedingten Zählungen
-
Having vs. Where in SQL: mit
HAVINGnach einer Zählung filtern - SQL Cheat Sheet: Aggregatfunktionen und der Rest von SQL auf einer Seite
Offizielle Dokumentation:
- PostgreSQL: Aggregatausdrücke
- MySQL: COUNT(DISTINCT)
- SQLite: count()
- SQL Server: COUNT und APPROX_COUNT_DISTINCT
Beekeeper Studio ist eine kostenlose & quelloffene Datenbank-GUI
Das beste SQL-Abfrage- & Editor-Tool, das ich je benutzt habe. Es bietet alles, was ich zum Verwalten meiner Datenbank brauche. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio ist schnell, intuitiv und einfach zu bedienen. Beekeeper unterstützt jede Menge Datenbanken und läuft hervorragend auf Windows, Mac und Linux.
Was User über Beekeeper Studio sagen
„Beekeeper Studio hat meinen alten SQL-Workflow komplett ersetzt. Es ist schnell, intuitiv und macht die Arbeit mit Datenbanken wieder zum Vergnügen.“
„Ich habe viele Datenbank-GUIs ausprobiert, aber Beekeeper trifft genau die richtige Balance zwischen Features und Einfachheit. Es funktioniert einfach.“