PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL:seleziona count(*) per le righe in cui è valida una condizione

Costruire sul tuo originale

La tua query originale era sulla strada giusta per escludere le righe offensive. Hai appena avuto > invece di = . Mancava il passaggio difficile da contare.

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;

Più breve

Probabilmente anche più veloce.

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;

Simile a domanda di @Clodoaldo o questa risposta precedente con ulteriori spiegazioni .
every(rating_id = 1) è più semplice di not bool_or(rating_id > 1) , ma esclude anche il rating < 1 - che probabilmente va bene (o anche meglio) per il tuo caso.

MySQL attualmente non implementa (SQL standard!) every() . Dal momento che vuoi eliminare solo rating_id > 1 , questa semplice espressione si adatta meglio alle tue esigenze e funziona in entrambi gli RDBMS:

HAVING max(rating_id) = 1

Il più corto

Con count(*) come funzione di aggregazione della finestra e senza 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;

Le funzioni della finestra vengono applicate dopo il passo aggregato. Basandosi su questo, otteniamo due aggregare i passaggi eseguiti in un unico livello di query:

  1. Piega l'equivalente (atr1_id, atr2_id) , escluse le righe in cui rating_id diverge esistono.
  2. Conta le righe rimanenti con una funzione finestra sull'intero set.

LIMIT 1 per ottenere una singola riga (tutte le righe sarebbero identiche).
MySQL non ha funzioni di finestra. Postgres solo.
Il più breve, non necessariamente il più veloce.

SQL Fiddle. (A pg9.2 poiché pg9.3 è attualmente offline.)