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:
- Piega l'equivalente
(atr1_id, atr2_id)
, escluse le righe in cuirating_id
diverge esistono. - 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.)