Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Przecięcie zapytania z activerecord

Twoje pytanie prawdopodobnie można rozwiązać bez przecięcia, coś takiego:

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

Poniżej znajduje się jednak ogólne podejście, którego używam do konstruowania skrzyżowań, takich jak zapytania w 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'))

Wygeneruje SQL w postaci:

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

Możesz utworzyć tyle podzapytań, ile jest to wymagane, przy użyciu powyższego podejścia w oparciu o dowolne warunki/połączenia itp., o ile każde podzapytanie zwraca identyfikator pasującej osoby w swoim zestawie wyników.

Każdy zestaw wyników podzapytania będzie połączony operatorem AND, ograniczając w ten sposób zestaw dopasowywania do przecięcia wszystkich podzapytań.

AKTUALIZUJ

Dla tych, którzy używają AR4, gdzie scoped została usunięta, moja druga odpowiedź zawiera semantycznie równoważny scoped polyfil, który all nie jest równoważnym zamiennikiem, pomimo tego, co sugeruje dokumentacja AR. Odpowiedz tutaj:W Rails 4, Model.scoped jest przestarzały, ale Model.all nie może go zastąpić



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak mogę osiągnąć funkcjonalność initcap w MySQL?

  2. Neo4j - Utwórz indeks za pomocą Cypher

  3. Jak sprawdzić, czy ciąg jest w formacie JSON, czy nie?

  4. Jak połączyć się z MySQL za pomocą Perla?

  5. Błąd pamięci przy użyciu json.dumps()