我有一个可以发布
的配置文件
。 profile
belongs_to :user
和 has_many :ratings
。
一个用户有_one :profile
,和has_many :ratings
。
A 评级 belongs_to :profile && belongs_to :user
。
这些是上述模型的模式:
Profile.rb
:
# == Schema Information
#
# Table name: profiles
#
# id :integer not null, primary key
# first_name :string
# last_name :string
# created_at :datetime not null
# updated_at :datetime not null
# user_id :integer
用户.rb
:
# == Schema Information
#
# Table name: users
#
# id :integer not null, primary key
# email :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# first_name :string
# last_name :string
Rating.rb
# == Schema Information
#
# Table name: ratings
#
# id :integer not null, primary key
# speed :integer default(0)
# passing :integer default(0)
# tackling :integer default(0)
# dribbling :integer default(0)
# profile_id :integer
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
请注意 coach = User.find(7)
。
当我执行此查询时:
>p = Profile.published.where(id: coach.ratings.order(passing: :desc).pluck(:profile_id))
(0.4ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 ORDER BY "ratings"."passing" DESC [["user_id", 7]]
Profile Load (1.1ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (52, 14, 24, 29) [["status", 1]]
> p.ids
=> [24, 14, 52]
注意 p.ids
生成的 profile.ids
的顺序。
但是,当我单独运行内部查询时,我得到了不同的顺序:
> coach.ratings.order(passing: :desc).limit(3).pluck(:profile_id)
(0.8ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 ORDER BY "ratings"."passing" DESC LIMIT $2 [["user_id", 7], ["LIMIT", 3]]
=> [52, 14, 24]
是什么导致了差异?为什么我不能让第一个查询始终产生与后一个查询相同的结果?
编辑 1
请注意,即使我在第一个查询中对 ID 的顺序进行硬编码,它仍会按原始顺序返回结果:
[19] pry(main)> cids = coach.ratings.order(passing: :desc).limit(3).pluck(:profile_id)
(0.7ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 ORDER BY "ratings"."passing" DESC LIMIT $2 [["user_id", 7], ["LIMIT", 3]]
=> [52, 14, 24]
[21] pry(main)> q = Profile.published.where(id: cids)
Profile Load (0.7ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (52, 14, 24) [["status", 1]]
[22] pry(main)> q.ids
=> [24, 14, 52]
编辑2
当我尝试以下 joins
查询时,它返回违反 published
状态的 profiles
(也就是返回具有 status 的配置文件: :unpublished
当它不应该时):
> a = Profile.joins(:ratings).where(status: :published, id: coach.ratings.pluck(:profile_id)).order('ratings.passing DESC')
(0.4ms) SELECT "ratings"."profile_id" FROM "ratings" WHERE "ratings"."user_id" = $1 [["user_id", 7]]
Profile Load (1.8ms) SELECT "profiles".* FROM "profiles" INNER JOIN "ratings" ON "ratings"."profile_id" = "profiles"."id" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.passing DESC [["status", 1]]
> o = Profile.find(29)
Profile Load (0.8ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."id" = $1 LIMIT $2 [["id", 29], ["LIMIT", 1]]
[59] pry(main)> o.status
=> "unpublished"
> a.ids
=> [52, 14, 24, 14, 24]
编辑3
来自上述查询的服务器错误:
PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ... AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.pa...
^
: SELECT DISTINCT "profiles".* FROM "profiles" INNER JOIN "ratings" ON "ratings"."profile_id" = "profiles"."id" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.passing DESC
编辑 3a
当我尝试从错误页面的 REPL 访问 @profiles
时,这是我得到的:
>> @profiles
!! #<ActiveRecord::StatementInvalid: PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list
LINE 1: ... AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.pa...
^
: SELECT DISTINCT "profiles".* FROM "profiles" INNER JOIN "ratings" ON "ratings"."profile_id" = "profiles"."id" WHERE "profiles"."status" = $1 AND "profiles"."id" IN (24, 52, 29, 14) ORDER BY ratings.passing DESC>
>>
最佳答案
原因是 where
查询没有按照输入的顺序返回记录。因此 where
中 id 的顺序不会影响结果。如果您想对 p
中的记录进行排序,您应该在 where
查询之后链接 order
。试试这个:
Profile.published.joins(:ratings).where(id: coach.ratings.pluck(:profile_id)).order('ratings.speed')
由 OP 编辑
所以原因是正确的,但是修复是错误的。
我终于通过以另一种方式提出这个问题找到了解决方法,并且 I got an answer .但为了完整起见,我在这里添加答案:
Profile.published
.joins(:ratings)
.where(ratings: { user_id: coach.id } )
.order('ratings.passing')
关于ruby-on-rails - 为什么这两个查询以不同的顺序检索记录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41295854/