当对象可能为 Nil 时求和

Posted

技术标签:

【中文标题】当对象可能为 Nil 时求和【英文标题】:Sum when object might be Nil 【发布时间】:2012-10-30 15:17:19 【问题描述】:

我有以下代码行:

@ranking_array  = User.joins(:bets, :choices).select("users.id, sum(bets.profitloss + choices.profitloss) as total_pl").group("users.id").order("total_pl DESC").map(&:id)

这给了我一个用户排名的数组——比如用户 X 排在第 25 位,依此类推。

但问题是,如果用户没有对任何选择下注,则结果将不包括该用户。

那么如何修复代码,即使选择的任何一个赌注都是零,它也会总结利润损失。

解决方案:

嗯.. 看来我必须结合你的两个答案才能使它起作用:)

我需要LEFT JOINCOALESCE,所以我得到了以下似乎可以工作的代码..

@ranking_array  = User.find(:all,
                  :joins =>  "LEFT JOIN `bets` ON bets.user_id = users.id LEFT JOIN `choices`ON choices.user_id = users.id",
                  :select => "users.id, sum(COALESCE(bets.profitloss, 0) + COALESCE(choices.profitloss, 0)) as total_pl",
                  :group =>  "users.id",
                  :order =>  "total_pl DESC").map(&:id)

非常感谢..我已经用了一整天的时间来解决这个问题..

问题是谁得到答案现在这是两者的结合?

【问题讨论】:

您可以注入一个 if 语句将任何空值转换为零,以确保总和中的计数。因为加零不会改变总数。 【参考方案1】:

我有一天也不得不使用这个,比如查看 COALESCE(something, 0) 它将返回一个或另一个。我认为你可以在 0 之前添加更多选项,因为它会一直持续到 0。

@ranking_array  = User.joins(:bets, :choices).select("users.id, sum(COALESCE(bets.profitloss, 0) + COALESCE(choices.profitloss, 0)) as total_pl").group("users.id").order("total_pl DESC").map(&:id)

【讨论】:

这个解决方案不是 db-agnostic,而是工作,除了 INNER JOIN【参考方案2】:

我自己不使用 Ruby,但您说您“缺少”未进行任何“下注”的用户的行。听起来您的实际查询正在生成一个INNER JOIN,而您需要一个LEFT JOIN。看看有没有this SO answer helps。

【讨论】:

当心!请记住,向NULL 添加一些内容会得到NULL。因此,如果您有未定义的字段,则必须强制转换值(请参阅@pjammer 的解决方案) Bob Duell:LEFT JOIN 效果更好。 @m_x:没有强制转换,只有使用 LEFT JOIN,mysql 和 Oracle 在玩家有空值时给出总计或空值。例如x 在记录中有历史投注,但昨天/今天他的投注无效。 y 根本没有赌注,所以全部为空。使用 LEFT JOIN,它返回 x = 20, y = (null) 。所以我很好奇你是否用“未定义”表示其他意思,因为在这个 (x,y) 示例中已经存在“未定义”字段。 我不确定我明白你的意思,我只想说如果你想做x+y,你必须做coalesce(x,0)+coalesce(y,0 ) .给出你的例子,如果你做 20+null,你的结果是 null,而不是 20。

以上是关于当对象可能为 Nil 时求和的主要内容,如果未能解决你的问题,请参考以下文章

释放 NSArray 时将对象设置为 nil

什么问题可能导致将 nib 文件的所有者设置为 nil?

当上下文为 nil 时,Swift Temp CoreData 对象无法设置 ivars

"指针"和"引用"大对比

"指针"和"引用"大对比

postgresql中的Rails json列不接受任何值,并在存储后调用时返回nil