选择用户。*和选择每个列之间有什么区别?

时间:2015-02-03 08:37:04

标签: ruby-on-rails postgresql join include distinct

我正在研究Ruby on Rails,并且有一些关于rails活动记录及其SQL转换的具体问题。

仅供参考,我使用的是postgresql,用户模型有很多状态,我想根据订购用户 状态的created_at 列。虽然我找到了解决方案User.includes(:statuses).order('statuses.created_at desc'),但我仍然有一些(可能是相互关联的)我不太了解的事情。

1)在rails控制台上,(为了更好的可读性,我进行了简化)

User.joins(:statuses).to_sql生成"SELECT users.* FROM users INNER JOIN statuses ON statuses.user_id = users.id"

User.includes(:statuses).references(:statuses).to_sql生成"SELECT users.id AS t0_r0, ...(simplified)... statuses.created_at AS t1_r3 FROM users LEFT OUTER JOIN statuses ON statuses.user_id = users.id"

选择用户有什么区别。*并选择每个列?

2)也在rails控制台上,

User.joins(:statuses).size生成SELECT COUNT(*) FROM users INNER JOIN statuses ON statuses.user_id = users.id => 155

User.includes(:statuses).references(:statuses).size生成SELECT COUNT(DISTINCT users.id) FROM users LEFT OUTER JOIN statuses ON statuses.user_id = users.id => 16

为什么包含会自动包含 distinct 子句,而加入则不会?

3)我尝试获取 statuses.created_at 订购的不同用户,并在用户上加入状态

我使用了这个条款:User.joins(:statuses).select('users.*, statuses.created_at').order('statuses.created_at desc').distinct。 (我应该使用 select statuses.created_at 归因于PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

但是这个条款不会删除重复!虽然User.joins(:statuses).select!('users.*, statuses.created_at').order('statuses.created_at desc').distinct.size生成 16 ,但当我实际执行它时,我看到了很多重复。

它生成SQL语句:SELECT DISTINCT users.*, statuses.created_at FROM users INNER JOIN statuses ON statuses.user_id = users.id ORDER BY statuses.created_at desc,它显示以下图像。

Result of User.joins(:statuses).select!('users.*, statuses.created_at').order('statuses.created_at desc').distinct

如您所见,它显示了我的记录的重复。

所以我的第三个问题是,为什么distinct子句不会删除重复(为什么 size 显示不同的结果)?

提前谢谢!

1 个答案:

答案 0 :(得分:1)

joins方法只为您生成SQL连接。任何个人用户都可以加入多种状态 - 这只是联接的内容,如果这不是您需要的,那么您可以自行处理它。 select子句默认为users.*,这样您就不会在两个表中不知不觉地以相同名称的列相互遮蔽(例如id列)

另一方面,

includes用于加载关联。这有时通过连接完成只是一个实现细节 - 在处理结果时有额外的代码,以便结果集只为每个用户提供一次(并将状态数据输入关联)。还包括所有列名称的别名,以处理名称相同的列

最后,您的distinct子句不会删除重复项,因为行不相同 - 包含statuses.created_at列,大多数行都不同。

size方法会忽略您的select子句,因此会对users.id进行计数 - 在这种情况下,distinct只会计算每个用户一次