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

SQL, gdzie połączony zbiór musi zawierać wszystkie wartości, ale może zawierać więcej

Grupuj według offer.id , a nie przez sports.name (lub sports.id ):

SELECT o.*
FROM   sports        s
JOIN   offers_sports os ON os.sport_id = s.id
JOIN   offers        o  ON os.offer_id = o.id
WHERE  s.name IN ('Bodyboarding', 'Surfing') 
GROUP  BY o.id  -- !!
HAVING count(*) = 2;

Zakładając typową implementację:

  • offer.id i sports.id są zdefiniowane jako klucz podstawowy.
  • sports.name jest zdefiniowany jako unikalny.
  • (sport_id, offer_id) w offers_sports jest zdefiniowany jako unikalny (lub PK).

Nie potrzebujesz DISTINCT w rachubę. I count(*) jest jeszcze trochę tańszy.

Powiązana odpowiedź z arsenałem możliwych technik:

  • Jak filtrować wyniki SQL w relacji ma wiele przejść

Dodane przez @max (OP) - to powyższe zapytanie przeniesione do ActiveRecord:

class Offer < ActiveRecord::Base
  has_and_belongs_to_many :sports
  def self.includes_sports(*sport_names)
    joins(:sports)
      .where(sports: { name: sport_names })
      .group('offers.id')
      .having("count(*) = ?", sport_names.size)
  end
end


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Nie można po prostu użyć nazwy tabeli PostgreSQL (relacja nie istnieje)

  2. Jak utworzyć sekwencję, jeśli nie istnieje?

  3. Limit czasu zapytania w pg-promise

  4. Funkcja okna Postgres i grupowanie według wyjątków

  5. Jak mogę zmienić kodowanie bazy danych dla bazy danych PostgreSQL za pomocą sql lub phpPgAdmin?