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:SELECT DISTINCTの場合、ORDERBY式は選択リストに表示される必要があります

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

クエリをさらに詳しく分析した後、最初のドラフトを修正する必要があります。クエリには、DISTINCTまたはGROUP 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 に答える