Rails Active Record find (: all ,: order =>) Problem

76

Ich kann anscheinend die Option ActiveRecord :: Base.find nicht verwenden: Bestellen Sie mehr als eine Spalte gleichzeitig.

Zum Beispiel habe ich ein "Show" -Modell mit Datum und teilnehmenden Spalten.

Wenn ich den folgenden Code ausführe:

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

Ich erhalte folgende Ergebnisse:

[#<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>]

Wenn ich den folgenden Code ausführe:

@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>]

Aber wenn ich renne:

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

ODER

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

ODER

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

Ich erhalte die gleichen Ergebnisse wie nur das Sortieren nach Datum:

 [#<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>]

Wo wie, ich möchte diese Ergebnisse erhalten:

[#<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>]

Dies ist die Abfrage, die aus den Protokollen generiert wird:

[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

Zum Schluss hier mein Modell:

  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

Was vermisse ich? Was mache ich falsch?

UPDATE: Danke für all Ihre Hilfe, aber es scheint, dass Sie alle genauso ratlos waren wie ich. Was das Problem löste, war das Wechseln der Datenbanken. Ich habe vom Standard-SQLite3 auf MySQL umgestellt.

CodingWithoutComments
quelle
Ich habe momentan kein Rails-Setup, um Ihren Code zu überprüfen. Welche Abfrage wird für die beiden Befehle generiert? Sie sollten in der Lage sein, die Protokolle in / logs zu überprüfen, um zu sehen.
YenTheFirst
Abfrage wäre in der Tat sehr hilfreich
Aivarsak
Vielleicht irrelevant, aber welche Version von AR verwenden Sie und welche DB?
Mike Woodhouse
[4; 35; 1mBenutzerlast (0,6 ms) [0m [0mSELECT * FROM "users" WHERE ("users". "Id" = 1) LIMIT 1 [0m [4; 36; 1mShow Load (3,0ms) [0m [ 0; 1mSELECT * FROM "zeigt" ORDER BY Datum ASC, Teilnahme an DESC [0m [4; 35; 1mUser Load (0,6ms) [0m [0mSELECT * FROM "users" WHERE ("users". "Id" = 1) [ 0m
CodingWithoutComments
Ich verwende sqllite3 und Rails Version 2.2.2
CodingWithoutComments

Antworten:

35

Ich stelle fest, dass in Ihrem ersten Beispiel das einfache : order => "date" , Datensatz 7 vor Datensatz 1 sortiert ist . In dieser Reihenfolge sehen Sie auch die Ergebnisse in der mehrspaltigen Sortierung, unabhängig davon, ob Sie nach Teilnahme sortieren.

Dies scheint mir sinnvoll zu sein, wenn die Daten nicht genau gleich wären und das Datum für 7 vor dem Datum für 1 liegt . Statt zu finden , dass der Zeitpunkt s genau dann zu sortieren fortfahren Equal Teilnahme , die Abfrage feststellt , dass die Daten nicht gleich ist und einfach sortieren nach , dass wie alle anderen Datensätze.

Ich sehe beim Durchsuchen, dass SQLite kein natives Verständnis der Datentypen DATE oder DATETIME hat und den Benutzern stattdessen die Wahl zwischen Gleitkommazahlen oder Text gibt, die sie selbst analysieren müssen. Ist es möglich, dass die wörtliche Darstellung der Daten in der Datenbank nicht genau gleich ist? Die meisten Menschen scheinen Notwendigkeit Funktionen Gebrauch Datum , so dass Termine verhalten sich wie man erwarten würde. Vielleicht gibt es eine Möglichkeit , Ihre Bestellung durch Spalte mit einer einzuwickeln Datumsfunktion , die Ihnen etwas Konkretes geben zu vergleichen, wie Datum (Datum) ASC, die Teilnahme an DESC . Ich bin nicht sicher, ob die Syntax funktioniert, aber es ist ein Bereich, in dem Sie Ihr Problem lösen müssen. Hoffentlich hilft das.

Brisma
quelle
Das macht Sinn - die DATE-Spalte könnte tatsächlich ein DATETIME oder ein anderer Bruchteil sein - also müssten Sie nach Datumsteilen bestellen ... Ja ... Guter Fang
Matt Rogish
4
Ich habe Datenbanken von SQLite3 auf MySQL umgestellt. Dies ließ das Problem verschwinden.
CodingWithoutComments
46

Könnte zwei Dinge sein. Zuerst,

Dieser Code ist veraltet:

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

sollte sein:

Model.order(...).all

Suchen wird mit den Optionen: all ,: order und vielen anderen Optionen nicht mehr unterstützt.

Zweitens Sie vielleicht eine default_scope gehabt haben, die eine gewisse Ordnung war Durchsetzung bevor Sie rief findauf Show.

Stundenlanges Stöbern im Internet führte mich zu einigen nützlichen Artikeln, die das Problem erklären:

thewillcole
quelle
1
Model.all (: order => ...) ist in Ordnung
mdpatrick
Model.order(...)ist besser
Weihnachten
In Rails 4.1 gibt Model.all (: order => "Feldname ASC") eine falsche Anzahl von Argumenten (1 für 0) Fehler. Die Model.order ("Feldname ASC") tut dies nicht. Dies wurde beim Upgrade einer alten Anwendung festgestellt.
Mark Davies
14

Das Problem ist, dass das Datum ein reserviertes sqlite3-Schlüsselwort ist . Ich hatte ein ähnliches Problem mit der Zeit , auch ein reserviertes Schlüsselwort, das in PostgreSQL gut funktionierte, aber nicht in sqlite3. Die Lösung benennt die Spalte um .

Siehe dies: Sqlite3 activerecord: order => "time DESC" sortiert nicht

oma
quelle
4

Ich bin gerade auf dasselbe Problem gestoßen, aber ich schaffe es, dass meine Abfrage in SQLite wie folgt funktioniert:

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

Ich hoffe, dies könnte jemandem helfen, Zeit zu sparen

Daniel Romero
quelle
3

ist es nicht nur :order => 'column1 ASC, column2 DESC'?

Eimantas
quelle
Ja, Entschuldigung - danke, dass Sie darauf hingewiesen haben. Das habe ich gemacht. In Frage korrigiert.
CodingWithoutComments
Das funktioniert aus irgendeinem Grund nicht. Ich habe es versucht. Irgendwelche anderen Ideen?
CodingWithoutComments
3

Stellen Sie sicher, dass Sie das Schema direkt auf Datenbankebene überprüfen. Ich habe mich schon einmal davon verbrannt, als beispielsweise eine Migration ursprünglich geschrieben wurde, um eine: datetime-Spalte zu erstellen. Ich habe sie lokal ausgeführt und dann die Migration auf ein: date optimiert, bevor sie tatsächlich bereitgestellt wurde. Somit sieht die Datenbank aller bis auf meine gut aus, und die Fehler sind subtil.

gtd
quelle
2

Ich verstehe, warum die Rails-Entwickler sich für eine sofort einsatzbereite Implementierung mit sqlite3 entschieden haben, aber MySQL ist meiner Meinung nach viel praktischer, IMHO. Mir ist klar, dass es davon abhängt, wofür Sie Ihre Rails-App erstellen, aber die meisten Leute werden die Standarddatei database.yml von sqlite3 auf MySQL umstellen.

Ich bin froh, dass Sie Ihr Problem gelöst haben.


quelle
konnte nicht mehr zustimmen. Entwickeln Sie mit derselben Datenbank, auf der Sie bereitstellen möchten. Es wird Ihnen auf lange Sicht so viele Kopfschmerzen ersparen.
brettish
2

Es ist gut, dass Sie Ihre Lösung gefunden haben. Aber es ist ein interessantes Problem. Ich habe es selbst direkt mit sqlite3 ausprobiert (nicht durch Schienen) und nicht das gleiche Ergebnis erzielt, für mich kam die Bestellung wie erwartet heraus.

Ich empfehle Ihnen, die sqlite3-Befehlszeilenanwendung zu starten und das Schema und die Abfragen dort zu überprüfen, wenn Sie dieses Problem weiter untersuchen möchten:

Dies zeigt Ihnen das Schema: .schema

Führen Sie dann einfach die select-Anweisung aus, wie sie in den Protokolldateien angezeigt wird: SELECT * FROM "shows" ORDER BY date ASC, attending DESC

Auf diese Weise sehen Sie, ob:

  1. Das Schema sieht so aus, wie Sie es möchten (dieses Datum ist beispielsweise ein Datum).
  2. Dass die Datumsspalte tatsächlich ein Datum und keinen Zeitstempel enthält (das heißt, dass Sie keine Tageszeit haben, die die Sortierung durcheinander bringt)
Jimmy Stenke
quelle
1

Ich verwende Rails 6 und Model.all (: order 'columnName DESC') funktioniert nicht. Ich habe die richtige Antwort in OrderInRails gefunden

Das ist sehr einfach.

@variable=Model.order('columnName DESC')
Kamrul
quelle
0

Dies könnte auch helfen:

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