Rails Active Record find (: all,: order =>) выпуск
кажется, я не могу использовать ActiveRecord::Base.найти вариант: заказ для более чем одного столбца одновременно.
например, у меня есть модель "шоу" с датой и посещением столбцов.
если я запускаю следующий код:
@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
что я упустил? Что я делаю не так?
UPDATE: Спасибо за всю вашу помощь, но кажется, что все вы были в тупике, как и я. Что решило проблему на самом деле это было переключение баз данных. Я переключился с sqlite3 по умолчанию на mysql.
9 ответов:
Я заметил, что в вашем первом примере простой : order = > "date", запись 7 сортируется перед записью 1. Этот порядок также является способом просмотра результатов в многоколоночной сортировке, независимо от того, выполняете ли вы сортировку по присутствию.
Это, казалось бы, имеет смысл для меня, если даты не были точно такими же, и дата для 7 до дата 1. Вместо того чтобы найти что датаС точно равный, то продолжая Сортировать по посещение запрос находит, что даты не равны и просто виды на что, как и все другие записи.
Я вижу из просмотра, что SQLite не имеет собственного понимания типов данных DATE или DATETIME и вместо этого дает пользователям выбор чисел с плавающей запятой или текста, который они должны анализировать сами. Возможно ли, что буквальное представление дат в базе данных не совсем равно? Наиболее люди, кажется, должны использовать функции даты так что даты ведут себя так, как вы ожидали бы. Возможно, есть способ обернуть ваш заказ по столбцу с помощью дата это даст вам что-то конкретное для сравнения, как дата (дата) ASC, посещение DESC. Я не уверен, что синтаксис работает, но это тема для решения вашей проблемы. Надеюсь, это поможет.
может быть две вещи. Во-первых,
этот код устарел:
Model.find(:all, :order => ...)
должно быть:
Model.order(...).all
Поиск больше не поддерживается с помощью :all, :order и многих других параметров.
второе, возможно, у вас был default_scope, который выполнял некоторые заказы, прежде чем вы позвонили
find
onShow
.часы копания в интернете привели меня к нескольким полезным статьям, которые объясняют вопрос:
проблема в том, что дата это зарезервированное ключевое слово sqlite3. У меня была аналогичная проблема с времени, также зарезервированное ключевое слово, которое отлично работало в PostgreSQL, но не в sqlite3. решение заключается в переименовании столбца.
Это: sqlite3 activerecord: order = > "time DESC" не сортирует
Я просто столкнулся с той же проблемой, но мне удается заставить мой запрос работать в SQLite следующим образом:
@shows = Show.order("datetime(date) ASC, attending DESC")
Я надеюсь, что это может помочь кому-то сэкономить время
убедитесь, что вы проверили схему непосредственно на уровне базы данных. Я уже обжегся этим раньше, где, например, миграция была изначально написана для создания столбца :datetime, и я запустил его локально, а затем настроил миграцию на a :date перед фактическим развертыванием. Таким образом, база данных каждого выглядит хорошо, за исключением моей, и ошибки тонкие.
Я понимаю, почему разработчики Rails пошли с sqlite3 для реализации из коробки, но MySQL намного практичнее, IMHO. Я понимаю, что это зависит от того, для чего вы создаете приложение Rails, но большинство людей собираются переключить базу данных по умолчанию.yml-файл из sqlite3 в MySQL.
рад, что вы решили вашу проблему.
это хорошо, что вы нашли свое решение. Но это интересная проблема. Я попробовал это сам непосредственно с sqlite3 (не проходя через rails) и не получил тот же результат, для меня заказ вышел, как ожидалось.
что я предлагаю вам сделать, если вы хотите продолжить копаться в этой проблеме, это запустить приложение командной строки sqlite3 и проверить схему и запросы там:
Это показывает вам схема:
.schema
а потом просто запустите инструкцию select, как она появилась в файлах журнала:
SELECT * FROM "shows" ORDER BY date ASC, attending DESC
таким образом, вы видите, если:
- схема выглядит так, как вы хотите (эта дата на самом деле дата, например)
- что столбец даты на самом деле содержит дату, а не метку времени (то есть, что у вас нет времени дня, которое портит сортировку)