左外连接和带有rails activerecord的where子句

时间:2015-10-12 10:41:35

标签: sql ruby-on-rails-4 activerecord left-join

我有两个模型:User和Rsvp。用户有很多Rsvps。

我想让所有在指定日期没有创建Rsvp的用户。

所以我写了这个:

   var format = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
    var fs = new FileStream(path, FileMode.Open);
    var ds = format.Deserialize(fs) as DataSet; 
    fs.Close();

    System.Data.DataTable table = ds.tables[0]; 
    table.Columns.Add("TEMP", typeof(string));
    DateTime lastSnap = DateTime.Now; 
    for (int i = 0; i < table.Rows.Count; i++) 
    {
        if (i % 100 == 0) 
        {       
            PrintToScreen((DateTime.Now - lastSnap).Seconds);           
            lastSnap = DateTime.Now;    
        }  
    }

但它只有在用户至少有一个Rsvp但不适用于&#39; date&#39;时才有效。当用户根本没有Rsvp时,它不起作用。

我尝试使用左外连接,但它不起作用。我必须错过一些东西:

scope :free, -> (date) { joins(:rsvps).where.not(rsvps: {created_at: date.beginning_of_day..date.end_of_day}) }

这是我的单元测试:

scope :free, -> (date) { joins("LEFT OUTER JOIN rsvps ON rsvps.user_id = users.id").where.not(rsvps: {created_at: date.beginning_of_day..date.end_of_day}) }

3 个答案:

答案 0 :(得分:3)

这应该有效: ELLCsInterfaceLogEvent aLogEvent = null; try { MongoDB.Bson.ObjectId UmbrellaLogIdAsObjectId = (ObjectId)UmbrellaLogId; BsonDocument logEventBsonDoc = new BsonDocument { {"UmbrellaLogId",(BsonValue)UmbrellaLogIdAsObjectId} }; // end of new BsonDocument objUtility = new Utility(); objUtility.Insert(logEventBsonDoc, "FMS_TM_MST_LogEvents"); string[] arrFields = { "UmbrellaLogId" }; IMongoQuery query = Query.EQ("UserID", (BsonValue)UmbrellaLogId); aLogEvent = DBConnection.database.GetCollection<ELLCsLogEvent>("FMS_TM_MST_LogEvents") .Find(query).SetFields(arrFields).ToList<ELLCsInterfaceLogEvent>().FirstOrDefault(); } catch (Exception ex) { string something = ex.Message; }

希望它有所帮助!

答案 1 :(得分:1)

通常joins返回具有至少一个Rsvp的用户。这就是我建议使用includes的原因。尝试这个(可能你必须修改条件因为我不确定它是你想要的):

scope :free, -> (date) { includes(:rsvps).where('rsvps.created_at != ?', date ).references(:rsvps) }

答案 2 :(得分:1)

你几乎做对了。您需要使用GROUP_BY语句,这样您才能获得重复的行。

scope :free, -> (date) do 
  joins("LEFT OUTER JOIN rsvps ON rsvps.user_id = users.id")
    .where.not(rsvps: {created_at: date.beginning_of_day..date.end_of_day})
    .group("users.id") # or just .group(:id)
end