选择 users.* 和选择每个单独的列之间有什么区别?
What is difference between selecting users.* and selecting each individual columns?
我正在研究 Ruby 关于 Rails,并且有一些关于 rails 活动记录及其 SQL 转换的具体问题。
仅供参考,我正在使用 postgresql,user 模型有很多 statuses,我想订购 users 基于 created_at 列的 statuses。虽然我找到了解决方案,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"
selecting users.* 和 selecting 每个单独的列之间有什么区别?
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
.
为什么 includes 自动包含 distinct 子句而 joins 不包含?
3) 我试图获得不同的 users 按 statuses.created_at 排序,statuses 加入 用户.
我使用了这个子句: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
,并显示下图。
如您所见,它显示了我的记录重复。
所以我的第三个问题是,为什么 distinct 子句不删除重复项(以及为什么 size 显示不同的结果)?
提前致谢!
joins
方法只会为您生成一个 SQL 连接。任何个人用户都可以加入多个状态 - 这正是加入所做的,如果这不是你需要的,那么由你来处理它。 select 子句默认为 users.*
,这样您就不会无意中在两个表中得到相同名称的列并相互遮蔽(例如 id
列)
另一方面,includes
用于预加载关联。这有时是通过连接来完成的,这只是一个实现细节——在处理结果时有额外的代码,以便结果集对每个用户只显示一次(并将状态数据馈送到关联中)。还包括别名所有列名以处理同名列
最后,您的 distinct 子句没有删除重复项,因为行不相同 - 包含 statuses.created_at
列,这在大多数行中都是不同的。
size
方法会忽略您的 select 子句,因此对 users.id
进行计数 - 在这种情况下,distinct 只会对每个用户计数一次
我正在研究 Ruby 关于 Rails,并且有一些关于 rails 活动记录及其 SQL 转换的具体问题。
仅供参考,我正在使用 postgresql,user 模型有很多 statuses,我想订购 users 基于 created_at 列的 statuses。虽然我找到了解决方案,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"
selecting users.* 和 selecting 每个单独的列之间有什么区别?
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
.
为什么 includes 自动包含 distinct 子句而 joins 不包含?
3) 我试图获得不同的 users 按 statuses.created_at 排序,statuses 加入 用户.
我使用了这个子句: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
,并显示下图。
如您所见,它显示了我的记录重复。
所以我的第三个问题是,为什么 distinct 子句不删除重复项(以及为什么 size 显示不同的结果)?
提前致谢!
joins
方法只会为您生成一个 SQL 连接。任何个人用户都可以加入多个状态 - 这正是加入所做的,如果这不是你需要的,那么由你来处理它。 select 子句默认为 users.*
,这样您就不会无意中在两个表中得到相同名称的列并相互遮蔽(例如 id
列)
includes
用于预加载关联。这有时是通过连接来完成的,这只是一个实现细节——在处理结果时有额外的代码,以便结果集对每个用户只显示一次(并将状态数据馈送到关联中)。还包括别名所有列名以处理同名列
最后,您的 distinct 子句没有删除重复项,因为行不相同 - 包含 statuses.created_at
列,这在大多数行中都是不同的。
size
方法会忽略您的 select 子句,因此对 users.id
进行计数 - 在这种情况下,distinct 只会对每个用户计数一次