PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

PostgreSQL - изберете count(*) за редове, където е изпълнено условие

Надграждане на вашия оригинал

Първоначалната ви заявка беше на правилния път, за да изключи редове в нарушение. Току-що имахте > вместо = . Липсваше сложната стъпка за преброяване.

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;

По-кратко

Вероятно и по-бързо.

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;

Подобно на заявката на @Clodoaldo или този по-ранен отговор с повече обяснения .
every(rating_id = 1) е по-просто от not bool_or(rating_id > 1) , но също така изключва rating < 1 - което вероятно е добре (или дори по-добре) за вашия случай.

MySQL в момента не прилага (стандартен SQL!) every() . Тъй като искате да елиминирате само rating_id > 1 , този прост израз отговаря по-точно на вашите изисквания и работи и в двете RDBMS:

HAVING max(rating_id) = 1

Най-кратък

С count(*) като агрегатна функция за прозорец и без подзаявка.

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;

Функциите на прозореца се прилагат след агрегатната стъпка. Надграждайки това, получаваме две обобщени стъпки, извършени в едно ниво на заявка:

  1. Сгъваем еквивалент (atr1_id, atr2_id) , с изключение на редове, където rating_id се различава съществуват.
  2. Преброяване на оставащите редове с прозоречна функция върху целия набор.

LIMIT 1 за да получите един ред (всички редове ще бъдат идентични).
MySQL няма прозоречни функции. Postgres само.
Най-кратък, не непременно най-бърз.

SQL Fiddle. (На pg9.2, тъй като pg9.3 в момента е офлайн.)



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да използвам bindparam() в персонализиран компилиран израз?

  2. Еволюция на отказоустойчивостта в PostgreSQL:Фаза на репликация

  3. java.lang.IllegalArgumentException:im ==null?

  4. PostgreSQL JDBC Null String, взет като байт

  5. Странна грешка при подреждане (бъг ли е?) при подреждане на две колони с еднакви стойности