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 75

9 ответов:

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

Это, казалось бы, имеет смысл для меня, если даты не были точно такими же, и дата для 7 до дата 1. Вместо того чтобы найти что датаС точно равный, то продолжая Сортировать по посещение запрос находит, что даты не равны и просто виды на что, как и все другие записи.

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

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

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

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

должно быть:

Model.order(...).all

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

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

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

проблема в том, что дата это зарезервированное ключевое слово sqlite3. У меня была аналогичная проблема с времени, также зарезервированное ключевое слово, которое отлично работало в PostgreSQL, но не в sqlite3. решение заключается в переименовании столбца.

Это: sqlite3 activerecord: order = > "time DESC" не сортирует

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

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

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

не только :order => 'column1 ASC, column2 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

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

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

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

Post.order(created_at: :desc)