1

我试图在我的数据库中查询与当前查看的记录(基于标记)相似的记录,我正在工作,但我想随机化顺序。

我的开发环境是mysql所以我会做类似的事情:

@tattoos = Tattoo.tagged_with(tags, :any => true).order("RAND()").limit(6)

哪个有效,但是我的生产环境是使用 postgresql 的 heroku,所以我尝试使用它:

@tattoos = Tattoo.tagged_with(tags, :any => true).order("RANDOM()").limit(6)

但我收到以下错误:

ActionView::Template::Error (PGError: ERROR: for SELECT DISTINCT, ORDER BY 表达式必须出现在选择列表中

SELECT  DISTINCT tattoos.* FROM "tattoos" JOIN taggings 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477  ON 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.taggable_id = tattoos.id AND 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.taggable_type = 'Tattoo' WHERE 
(tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 3 OR 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 4 OR 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 5 OR 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 24 OR 
tattoos_taggings_color_fantasy_newschool_nerdy_tv_477.tag_id = 205) ORDER BY RANDOM() LIMIT 6):
4

2 回答 2

2

在更仔细地分析了查询之后,我必须更正我的初稿。查询将需要一个DISTINCTGROUP BY它的方式。

(可能)重复tattoos.*来自第一次加入(可能)表中的多行 taggingsDISTINCT然后,您的查询引擎尝试以语法上非法的方式使用 - 再次消除此类重复项。

DISTINCT基本上按从左到右的结果列对结果行进行排序,并为每组重复项选择第一个。这就是为什么最左边的ORDER BY列必须与SELECT列表匹配。

MySQL 比较宽松,允许非标准使用DISTINCT,但 PostgreSQL 会抛出错误。

ORM 经常会产生无效的 SQL 语句(毕竟它们只是拐杖)。但是,如果您使用适当的 PostgreSQL 库,则不应一开始就产生这样的非法语句。我不是 Ruby 专家,但这里有些可疑。

查询也很丑陋和低效

有几种方法可以修复它。例如:

SELECT * 
FROM  (<query without ORDER BY and LIMIT>) x
ORDER  BY RANDOM()
LIMIT  6

或者,更好的是,用这个更快、更简洁的替代方法重写查询:

SELECT ta.*
FROM   tattoos ta
WHERE  EXISTS (
    SELECT 1
    FROM   taggings t
    WHERE  t.taggable_id = ta .id
    AND    t.taggable_type = 'Tattoo'
    AND    t.tag_id IN (3, 4, 5, 24, 205)
    )
ORDER  BY RANDOM()
LIMIT  6;

您必须自己在 Ruby 中实现它。

于 2012-05-27T16:56:35.450 回答
0

不确定随机,因为它应该可以工作。但记下http://railsforum.com/viewtopic.php?id=36581

其中有可能适合您的代码

/lib/agnostic_random.rb
module AgnosticRandom
  def random
    case DB_ADAPTER
      when "mysql" then "RAND()"
      when "postgresql" then "RANDOM()"
    end
  end
end

/initializers/extend_ar.rb (name doesn't matter)
ActiveRecord::Base.extend AgnosticRandom
于 2012-05-27T17:05:34.217 回答