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_id
existieren. - 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.)