web-dev-qa-db-ja.com

Rails Activerecord find(:all、:order =>)issue

ActiveRecord :: Base.findオプション:orderを一度に複数の列に使用できないようです。

たとえば、日付と出席列を持つ「表示」モデルがあります。

次のコードを実行すると:

@shows = Show.find(:all, :order => "date")

次の結果が得られます。

[#<Show id: 7, date: "2009-04-18", attending: 2>, 
 #<Show id: 1, date: "2009-04-18", attending: 78>, 
 #<Show id: 2, date: "2009-04-19", attending: 91>, 
 #<Show id: 3, date: "2009-04-20", attending: 16>,
 #<Show id: 4, date: "2009-04-21", attending: 136>]

次のコードを実行すると:

@shows = Show.find(:all, :order => "attending DESC")

[#<Show id: 4, date: "2009-04-21", attending: 136>,
 #<Show id: 2, date: "2009-04-19", attending: 91>,
 #<Show id: 1, date: "2009-04-18", attending: 78>,
 #<Show id: 3, date: "2009-04-20", attending: 16>,
 #<Show id: 7, date: "2009-04-18", attending: 2>]

しかし、私が実行した場合:

@shows = Show.find(:all, :order => "date, attending DESC")

OR

@shows = Show.find(:all, :order => "date, attending ASC")

OR

@shows = Show.find(:all, :order => "date ASC, attending DESC")

日付による並べ替えのみと同じ結果が得られます。

 [#<Show id: 7, date: "2009-04-18", attending: 2>, 
 #<Show id: 1, date: "2009-04-18", attending: 78>, 
 #<Show id: 2, date: "2009-04-19", attending: 91>, 
 #<Show id: 3, date: "2009-04-20", attending: 16>,
 #<Show id: 4, date: "2009-04-21", attending: 136>]

どこで、私はこれらの結果を取得したい:

[#<Show id: 1, date: "2009-04-18", attending: 78>,
#<Show id: 7, date: "2009-04-18", attending: 2>, 
 #<Show id: 2, date: "2009-04-19", attending: 91>, 
 #<Show id: 3, date: "2009-04-20", attending: 16>,
 #<Show id: 4, date: "2009-04-21", attending: 136>]

これは、ログから生成されるクエリです。

[4;35;1mUser Load (0.6ms)[0m   [0mSELECT * FROM "users" WHERE ("users"."id" = 1) LIMIT 1[0m
[4;36;1mShow Load (3.0ms)[0m   [0;1mSELECT * FROM "shows" ORDER BY date ASC, attending DESC[0m
[4;35;1mUser Load (0.6ms)[0m   [0mSELECT * FROM "users" WHERE ("users"."id" = 1) [0m

最後に、ここに私のモデルがあります:

  create_table "shows", :force => true do |t|
    t.string   "headliner"
    t.string   "openers"
    t.string   "venue"
    t.date     "date"
    t.text     "description"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.decimal  "price"
    t.time     "showtime"
    t.integer  "attending",   :default => 0
    t.string   "time"
  end

私は何が欠けていますか?何が間違っていますか?

更新:すべてのあなたの助けに感謝します、しかし、あなたのすべてが私と同じくらい困惑しているようです。問題を解決したのは実際にデータベースを切り替えることでした。デフォルトのsqlite3からmysqlに切り替えました。

75

最初の例では、単純な:order => "date"、レコード7はレコード1の前にソートされています。この順序は、出席順で並べ替えるかどうかに関係なく、複数列の並べ替えで結果を表示する方法でもあります。

日付が正確に同じでなく、7の日付が1の日付より前であれば、これは理にかなっているように思えます。 date sが正確に等しいことを見つける代わりにattendingによるソートに進む代わりに、クエリは日付が等しくないことを検出し、他のすべてのレコードと同様に単純にソートします。 。

ブラウズしてみると、SQLiteはDATEまたはDATETIMEデータ型をネイティブに理解しておらず、代わりにユーザーが自分で解析する必要のある浮動小数点数またはテキストを選択できます。データベース内の日付のリテラル表現が正確に等しくない可能性はありますか?ほとんどの人は 日付関数を使う が必要なようです。おそらく、 date function で列ごとに注文をラップする方法があり、それはdate(date)ASC、DESCに参加するのように、比較する具体的なものを提供します。構文が機能するかどうかはわかりませんが、問題を解決するために検討すべき領域です。お役に立てば幸いです。

36
brism

2つの可能性があります。まず、

このコードは非推奨です:

Model.find(:all, :order => ...)

する必要があります:

Model.order(...).all

Findは、:all、:order、および他の多くのオプションではサポートされなくなりました。

第二に、findShowを呼び出す前に、何らかの順序付けを強制するdefault_scopeがあったかもしれません。

インターネットで何時間も掘り下げた結果、この問題を説明する有用な記事がいくつか見つかりました。

45
thewillcole

問題は、date予約されたsqlite3キーワードであるということです。 timeも同様の問題があり、これも予約キーワードであり、PostgreSQLでは正常に機能しましたが、sqlite3では機能しませんでした。 ソリューションは列の名前を変更しています

これを参照してください: Sqlite3 activerecord:order => "time DESC"はソートしません

14
oma

私はちょうど同じ問題に遭遇しましたが、次のようにSQLiteでクエリを動作させることができました:

@shows = Show.order("datetime(date) ASC, attending DESC")

これが誰かが時間を節約するのに役立つことを願っています

4
Daniel Romero

:order => 'column1 ASC, column2 DESC'だけではありませんか?

3
Eimantas

データベースレベルでスキーマを直接確認してください。たとえば、最初に:datetimeカラムを作成するために移行が記述され、ローカルで実行した後、実際にデプロイする前に移行を:dateに微調整しました。したがって、私のデータベースを除いて、誰のデータベースも見栄えがよく、バグは微妙です。

3
gtd

解決策を見つけたのは良いことです。しかし、それは興味深い問題です。 sqlite3を使用して(Railsを経由せずに)直接試してみたところ、同じ結果が得られませんでした。私にとっては、期待どおりに注文が出ました。

この問題をさらに掘り下げたい場合、sqlite3コマンドラインアプリケーションを起動し、そこでスキーマとクエリを確認することをお勧めします。

これにより、スキーマが表示されます:.schema

そして、ログファイルに表示されたselect文を実行します。SELECT * FROM "shows" ORDER BY date ASC, attending DESC

そのように表示される場合:

  1. スキーマは希望どおりに見えます(その日付は実際にはたとえば日付です)
  2. 日付列にタイムスタンプではなく日付が実際に含まれていること(つまり、並べ替えを台無しにする時刻がないこと)
2
Jimmy Stenke

私はなぜRails devsがすぐに使える実装のためにsqlite3と一緒に行ったのか理解していますが、MySQLははるかに実用的です、私見。 Rails appですが、ほとんどの人はデフォルトのdatabase.ymlファイルをsqlite3からMySQLに切り替えます。

問題を解決していただきありがとうございます。

2
user59278

これも役立つかもしれません:

Post.order(created_at: :desc)
0
Maximus S