Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Verfügbare Benutzer an einem bestimmten Datum auflisten

Hier ist eine Möglichkeit, es zu modellieren. Angenommen, wir haben ein Modell „Engagement“, das ein Startdatum, ein Enddatum und einen Namen hat. Ein Engagement hat viele Benutzer, über eine andere Join-Tabelle namens „user_engagements“ (mit entsprechendem UserEngagement-Modell). Also haben wir

User
  has_many :user_engagements
  has_many :engagements, :through => :user_engagements

Engagement
  #fields - starts_at, ends_at (both datetime)
  has_many :user_engagements
  has_many :users, :through => :user_engagements

UserEngagement
  belongs_to :user
  belongs_to :engagement

Jetzt haben wir ein nettes einfaches Schema. Ein Engagement modelliert im Grunde etwas, das passiert, und user_engagements modelliert Benutzer, die dafür gebucht sind. Wir gehen davon aus (nicht in den Code geschrieben), dass sie, wenn sie etwas tun, für nichts anderes verfügbar sind.

Unsere nächste Aufgabe besteht darin, eine Methode zu schreiben, die Benutzer zurückgibt, die innerhalb eines bestimmten Zeitraums verfügbar sind, dh ein neues Engagement. Also machen wir eine Verlobung und wir wollen alle Benutzer, die keine Verlobung haben, die sich mit unserer neuen Verlobung überschneidet. Ich denke, der einfachste Weg, dies zu tun, besteht darin, alle Benutzer zu finden, die ein Crossover-Engagement haben, und dann alle Benutzer zurückzugeben, die sie nicht sind. Wenn du weißt, was ich meine. Eine genauere Art zu sagen, dass e2 sich mit e1 überschneidet, ist, dass e2 vor dem Ende von e1 beginnt UND nach dem Beginn von e1 endet.

Lassen Sie uns dies zu einer Methode eines Engagement-Objekts machen, da es vollständig von den Daten eines Engagements abhängig ist.

#in Engagement
def unavailable_user_ids
  User.find(:all, :include => [:user_engagements], :select => "users.id", :conditions => ["user_engagements.starts_at < ? and user_engagements.ends_at > ?", self.ends_at, self.starts_at]).collect(&:id)
end

def available_users
  User.find(:all, :conditions => ["id not in (?)", self.unavailable_user_ids])
end

Ich habe das Gefühl, dass es einen effizienteren Weg gibt, dies in einer Abfrage zu erhalten, aber ich kann den Finger nicht auf die SQL legen.