PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL - select count(*) für Zeilen, in denen eine Bedingung gilt

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:

  1. Äquivalent (atr1_id, atr2_id) falten , ausgenommen Zeilen mit abweichender rating_id existieren.
  2. 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.)