PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PostgreSQL - selecione count(*) para linhas onde uma condição é válida

Com base no seu original


Sua consulta original estava no caminho certo para excluir linhas ofensivas. Você acabou de ter > em vez de = . O passo complicado para contar estava faltando.
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;

Curto


Provavelmente mais rápido também.
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;

Semelhante à consulta de @Clodoaldo ou esta resposta anterior com mais explicações .
every(rating_id = 1) é mais simples que not bool_or(rating_id > 1) , mas também exclui rating < 1 - o que provavelmente é bom (ou até melhor) para o seu caso.

MySQL atualmente não implementa (SQL padrão!) every() . Como você deseja apenas eliminar rating_id > 1 , essa expressão simples se ajusta melhor aos seus requisitos e funciona em ambos os RDBMS:
HAVING max(rating_id) = 1

O mais curto


Com count(*) como função de agregação de janela e sem subconsulta.
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;

As funções da janela são aplicadas depois a etapa agregada. Com base nisso, temos dois etapas agregadas feitas em um único nível de consulta:
  1. Fold equivalente (atr1_id, atr2_id) , excluindo linhas em que rating_id divergente existe.
  2. Conte as linhas restantes com uma função de janela em todo o conjunto.

LIMIT 1 para obter uma única linha (todas as linhas seriam idênticas).
O MySQL não possui funções de janela. Postgre apenas.
O mais curto, não necessariamente o mais rápido.

SQL Fiddle. (Na página 9.2 já que a página 9.3 está offline no momento.)