sql >> Databasteknik >  >> RDS >> Mysql

Fråga korsning med activerecord

Din fråga är förmodligen lösbar utan skärningspunkt, ungefär som:

Person.joins(:services).where(services: {service_type: [1,2]}).group(
   people: :id).having('COUNT("people"."id")=2')

Men följande är ett allmänt tillvägagångssätt som jag använder för att konstruera korsningar som frågor i ActiveRecord:

class Service < ActiveRecord::Base
  belongs_to :person

  def self.with_types(*types)
    where(service_type: types)
  end
end

class City < ActiveRecord::Base
  has_and_belongs_to_many :services
  has_many :people, inverse_of: :city
end

class Person < ActiveRecord::Base
  belongs_to :city, inverse_of: :people

  def self.with_cities(cities)
    where(city_id: cities)
  end

  def self.with_all_service_types(*types)
    types.map { |t|
      joins(:services).merge(Service.with_types t).select(:id)
    }.reduce(scoped) { |scope, subquery|
      scope.where(id: subquery)
    }
  end
end

Person.with_all_service_types(1, 2)
Person.with_all_service_types(1, 2).with_cities(City.where(name: 'Gold Coast'))

Det kommer att generera SQL i formen:

SELECT "people".*
  FROM "people"
 WHERE "people"."id" in (SELECT "people"."id" FROM ...)
   AND "people"."id" in (SELECT ...)
   AND ...

Du kan skapa så många underfrågor som krävs med ovanstående tillvägagångssätt baserat på alla villkor/kopplingar etc så länge som varje underfråga returnerar id:t för en matchande person i dess resultatuppsättning.

Varje delfrågeresultatuppsättning kommer att OCH sammanföras, vilket begränsar matchningsuppsättningen till skärningspunkten mellan alla underfrågor.

UPPDATERA

För de som använder AR4 där scoped togs bort, ger mitt andra svar en semantiskt likvärdig scoped polyfil som all är inte en likvärdig ersättning för trots vad AR-dokumentationen antyder. Svara här:Med Rails 4 är Model.scoped utfasad men Model.all kan inte ersätta den



  1. SQL Inner Join

  2. Databasbelastningsbalansering i molnet - MySQL Master Failover med ProxySQL 2.0:Part One (Deployment)

  3. Android Room Database, hämta det specifika värdet för den senaste posten

  4. Akta dig för vilseledande data från SET STATISTICS IO