Auf Ihrem Original aufbauen
Ihre ursprüngliche Abfrage war auf dem richtigen Weg, anstößige Zeilen auszuschließen. Sie hatten gerade > statt = . Der knifflige Schritt zum Zählen fehlte.
SELECT count(*) AS ct
FROM (
SELECT 1
FROM compatibility c
WHERE rating_id = 1
AND NOT EXISTS (
SELECT 1
FROM compatibility c2
WHERE c2.rating_id > 1
AND (c2.attr1_id = c.attr1_id AND c2.attr2_id = c.attr2_id OR
c2.attr1_id = c.attr2_id AND c2.attr2_id = c.attr1_id))
GROUP BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
) sub;
Kürzer
Wahrscheinlich auch schneller.
SELECT count(*) AS ct
FROM (
SELECT 1 -- selecting more columns for count only would be a waste
FROM compatibility
GROUP BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
HAVING every(rating_id = 1)
) sub;
Ähnlich wie @Clodoaldos Anfrage
oder diese frühere Antwort mit mehr Erklärung
.every(rating_id = 1) ist einfacher als not bool_or(rating_id > 1) , schließt aber auch rating < 1 aus - was für Ihren Fall wahrscheinlich in Ordnung (oder sogar besser) ist.
MySQL implementiert derzeit nicht (Standard-SQL!) every() . Da Sie nur rating_id > 1 eliminieren möchten , dieser einfache Ausdruck passt besser zu Ihren Anforderungen und funktioniert in beiden RDBMS:
HAVING max(rating_id) = 1
Am kürzesten
Mit count(*) als Fensteraggregatfunktion und ohne Unterabfrage.
SELECT count(*) OVER () AS ct
FROM compatibility
GROUP BY least(attr1_id, attr2_id), greatest(attr1_id, attr2_id)
HAVING max(rating_id) = 1
LIMIT 1;
Fensterfunktionen werden nach angewendet der Aggregatschritt. Darauf aufbauend erhalten wir zwei aggregierte Schritte, die auf einer einzigen Abfrageebene ausgeführt werden:
- Äquivalent
(atr1_id, atr2_id)falten , ausgenommen Zeilen mit abweichenderrating_idexistieren. - Zählen Sie verbleibende Zeilen mit einer Fensterfunktion über den gesamten Satz.
LIMIT 1 um eine einzelne Zeile zu erhalten (alle Zeilen wären identisch).
MySQL hat keine Fensterfunktionen. Postgres nur.
Am kürzesten, nicht unbedingt am schnellsten.
SQL-Fiddle. (Auf pg9.2, da pg9.3 derzeit offline ist.)