PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

PostgreSQL - wybierz count(*) dla wierszy, w których spełniony jest warunek

Budowanie na oryginale

Twoje pierwotne zapytanie było na właściwej ścieżce, aby wykluczyć obraźliwe wiersze. Właśnie miałeś > zamiast = . Brakowało trudnego kroku do policzenia.

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;

Krótszy

Prawdopodobnie też szybciej.

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;

Podobne do zapytanie @Clodoaldo lub ta wcześniejsza odpowiedź z dodatkowymi wyjaśnieniami .
every(rating_id = 1) jest prostsze niż not bool_or(rating_id > 1) , ale wyklucza także rating < 1 - co prawdopodobnie jest w porządku (lub nawet lepiej) w twoim przypadku.

MySQL obecnie nie implementuje (standardowy SQL!) every() . Ponieważ chcesz wyeliminować tylko rating_id > 1 , to proste wyrażenie lepiej pasuje do Twoich wymagań i działa w obu RDBMS:

HAVING max(rating_id) = 1

Najkrótszy

Z count(*) jako funkcja agregująca okna i bez podzapytania.

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;

Funkcje okna są stosowane po zagregowany krok. Bazując na tym, otrzymujemy dwa agregacja kroków wykonanych na poziomie pojedynczego zapytania:

  1. Zwiń odpowiednik (atr1_id, atr2_id) , z wyłączeniem wierszy, w których rozbieżny rating_id istnieje.
  2. Policz pozostałe wiersze za pomocą funkcji okna w całym zestawie.

LIMIT 1 aby uzyskać pojedynczy wiersz (wszystkie wiersze byłyby identyczne).
MySQL nie posiada funkcji okna. Postgres tylko.
Najkrótszy, niekoniecznie najszybszy.

Skrzypce SQL. (Na stronie 9.2, ponieważ strona 9.3 jest obecnie offline.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dlaczego najlepiej przechowywać numer telefonu jako ciąg, a nie jako liczbę całkowitą?

  2. PostgreSQL tworzy indeks na podstawie rzutu od ciągu do daty

  3. Dlaczego polecenie \dt daje - nie znaleziono relacji?

  4. SQL LIMIT a instrukcja JDBC setMaxRows. Który jest lepszy?

  5. java.lang.ClassNotFoundException:org.postgresql.Driver