sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL - selecteer count(*) voor rijen waar een voorwaarde geldt

Voortbouwend op je origineel

Uw oorspronkelijke zoekopdracht was op de goede weg om aanstootgevende rijen uit te sluiten. Je had net > in plaats van = . De lastige stap om te tellen ontbrak.

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;

Korter

Waarschijnlijk ook sneller.

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;

Vergelijkbaar met De vraag van @Clodoaldo of dit eerdere antwoord met meer uitleg .
every(rating_id = 1) is eenvoudiger dan not bool_or(rating_id > 1) , maar sluit ook rating < 1 uit - wat waarschijnlijk goed (of zelfs beter) is voor jouw geval.

MySQL implementeert momenteel niet (standaard SQL!) every() . Omdat je alleen rating_id > 1 wilt verwijderen , deze eenvoudige uitdrukking past beter bij uw vereisten en werkt in beide RDBMS:

HAVING max(rating_id) = 1

Kortste

Met count(*) als vensteraggregatiefunctie en zonder subquery.

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;

Vensterfuncties worden na . toegepast de aggregatiestap. Hierop voortbouwend krijgen we twee geaggregeerde stappen gedaan op één zoekniveau:

  1. Equivalent (atr1_id, atr2_id) , met uitzondering van rijen waar afwijkende rating_id bestaan.
  2. Tel resterende rijen met een vensterfunctie over de hele set.

LIMIT 1 om een ​​enkele rij te krijgen (alle rijen zouden identiek zijn).
MySQL heeft geen vensterfuncties. Postgres alleen.
Kortste, niet per se de snelste.

SQL Fiddle. (Op pg9.2 aangezien pg9.3 momenteel offline is.)



  1. Kan een gedistribueerde transactie niet starten

  2. Hoe queryparameters in MySQL Query Browser in te stellen?

  3. Veroorzaakt door:java.lang.NoSuchMethodError:org.postgresql.core.BaseConnection.getEncoding()Lorg/postgresql/core/Encoding;

  4. Loop door mysql_fetch_array in PHP