Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Listando usuários disponíveis em uma determinada data


Aqui está uma maneira de modelá-lo. Digamos que temos um modelo 'Engagement' que tem uma data e hora de início, uma data e hora de término e um nome. Um engajamento tem muitos usuários, por meio de outra tabela de junção chamada 'user_engagements' (com o modelo UserEngagement correspondente). Então nós temos
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

Agora temos um bom esquema simples. Um engajamento basicamente modela algo que está acontecendo, e user_engagements modela usuários que estão agendados para fazer isso. Temos uma suposição (não escrita no código) de que, quando eles estão fazendo algo, não estão disponíveis para fazer mais nada.

Nossa próxima tarefa é escrever um método que retorne usuários disponíveis em um determinado período de tempo, ou seja, um novo engajamento. Então, fazemos um engajamento e queremos todos os usuários que não têm um engajamento que cruze com o nosso novo engajamento. Acho que a maneira mais simples de fazer isso pode ser encontrar todos os usuários que têm um engajamento de crossover e, em seguida, retornar todos os usuários que não são eles. Se você souber o que quero dizer. Uma maneira mais precisa de dizer que e2 cruza com e1 é que e2 começa antes do final de e1 E termina após o início de e1.

Vamos fazer disso um método de um objeto de engajamento, pois é totalmente dependente dos dados de um engajamento.
#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

Eu sinto que há uma maneira mais eficiente de obter isso em uma consulta, mas não consigo colocar meu dedo no sql.