Рельсы Active Record находят (: all,: order =>) проблему - PullRequest
75 голосов
/ 13 апреля 2009

Кажется, я не могу использовать опцию ActiveRecord :: Base.find: заказывать более одного столбца за раз.

Например, у меня есть модель «Показать» с датой и посещающими столбцами.

Если я запускаю следующий код:

@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")

ИЛИ

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

ИЛИ

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

Ответы [ 9 ]

45 голосов
/ 14 января 2012

Может быть две вещи. Во-первых,

Этот код устарел:

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

должно быть:

Model.order(...).all

Поиск больше не поддерживается с: all,: order и многими другими параметрами.

Во-вторых, у вас мог быть default_scope, который навязывал некоторый порядок, прежде чем вы вызвали find на Show.

Часы копания в интернете привели меня к нескольким полезным статьям, объясняющим проблему:

36 голосов
/ 13 апреля 2009

Я заметил, что в вашем первом примере простая : order => "date" , запись 7 сортируется перед записью 1 . Этот порядок также показывает, как вы видите результаты в сортировке по нескольким столбцам, независимо от того, сортируете ли вы по посещаемости.

Мне кажется, что это имеет смысл, если даты не совпадают, а дата для 7 предшествует дате для 1 . Вместо того чтобы обнаружить, что date s в точности равны, а затем приступить к сортировке по , сопровождающему , запрос обнаруживает, что даты не равны, и просто сортирует по тому же признаку, что и все другие записи. 1017 *

Я вижу из просмотра, что SQLite не имеет собственного представления о типах данных DATE или DATETIME и вместо этого предоставляет пользователям выбор чисел с плавающей запятой или текста, который они должны анализировать сами. Возможно ли, что буквальное представление дат в базе данных не точно совпадает? Большинству людей, кажется, нужно использовать функции даты , чтобы даты вели себя так, как вы ожидаете. Возможно, есть способ обернуть ваш заказ по столбцу с помощью функции date , которая даст вам что-то конкретное для сравнения, например date (date) ASC, посещая DESC . Я не уверен, что синтаксис работает, но это область, на которую нужно обратить внимание для решения вашей проблемы. Надеюсь, это поможет.

14 голосов
/ 28 апреля 2010

Проблема в том, что date является зарезервированным ключевым словом sqlite3 . У меня была похожая проблема с time , также зарезервированным ключевым словом, которое отлично работало в PostgreSQL, но не в sqlite3. Решение переименовывает столбец .

См. Это: Sqlite3 activerecord: order => "time DESC" не сортируется

4 голосов
/ 14 февраля 2013

Я только что столкнулся с той же проблемой, но мне удается заставить мой запрос работать в SQLite, например так:

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

Надеюсь, это поможет кому-то сэкономить время

3 голосов
/ 16 апреля 2009

Обязательно проверьте схему на уровне базы данных напрямую. Раньше я был сожжен этим, когда, например, изначально была написана миграция для создания столбца: datetime, и я запустил ее локально, а затем настроил миграцию на: date до фактического развертывания. Таким образом, база данных у всех выглядит хорошо, кроме моей, и ошибки неуловимы.

3 голосов
/ 13 апреля 2009

не только ли :order => 'column1 ASC, column2 DESC'?

2 голосов
/ 21 апреля 2009

Хорошо, что вы нашли свое решение. Но это интересная проблема. Я испытал это непосредственно непосредственно с sqlite3 (не проходя через рельсы) и не получил тот же самый результат, для меня заказ вышел, как ожидалось.

Если я хочу продолжить изучение этой проблемы, я предлагаю вам запустить приложение командной строки sqlite3 и проверить там схему и запросы:

Здесь показана схема: .schema

А затем просто запустите оператор SELECT, как показано в файлах журнала: SELECT * FROM "shows" ORDER BY date ASC, attending DESC

Таким образом, вы видите, если:

  1. Схема выглядит так, как вы хотите (например, эта дата фактически является датой)
  2. То, что столбец даты на самом деле содержит дату, а не метку времени (то есть, у вас нет времени дня, которое портит сортировку)
2 голосов
/ 19 апреля 2009

Я понимаю, почему разработчики Rails пошли с sqlite3 для реализации из коробки, но MySQL намного практичнее, ИМХО. Я понимаю, что это зависит от того, для чего вы строите свое Rails-приложение, но большинство людей собирается переключить файл database.yml по умолчанию с sqlite3 на MySQL.

Рад, что вы решили свою проблему.

0 голосов
/ 22 июля 2016

Это тоже может помочь:

Post.order(created_at: :desc)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...