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

SQL, където обединеният набор трябва да съдържа всички стойности, но може да съдържа повече

Групиране по offer.id , а не от sports.name (или 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;

Приемайки типичната реализация:

  • offer.id и sports.id са дефинирани като първичен ключ.
  • sports.name е определен уникален.
  • (sport_id, offer_id) в offers_sports е дефиниран уникален (или PK).

Нямате нужда от DISTINCT в преброяването. И count(*) е дори малко по-евтино, все пак.

Свързан отговор с арсенал от възможни техники:

  • Как да филтрирате SQL резултати във връзка има-много-през

Добавено от @max (ОП) - това е горната заявка, въведена в 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. В рамките на функция за задействане, как да получите кои полета се актуализират

  2. PostgreSQL репликация за аварийно възстановяване

  3. Където условие за съединена маса в Sequelize ORM

  4. Определяне на OID на таблица в Postgres 9.1?

  5. Rails:FATAL - Удостоверяването на партньора не бе успешно за потребител (PG::Error)