Я намагаюся знайти всіх користувачів з ідентифікатором, більшим за 200, але у мене виникають проблеми з конкретним синтаксисом.
User.where(:id > 200)
і
User.where("? > 200", :id)
обоє не змогли.
Будь-які пропозиції?
Я намагаюся знайти всіх користувачів з ідентифікатором, більшим за 200, але у мене виникають проблеми з конкретним синтаксисом.
User.where(:id > 200)
і
User.where("? > 200", :id)
обоє не змогли.
Будь-які пропозиції?
Відповіді:
Спробуйте це
User.where("id > ?", 200)
?
, а не вкладенню 200
?
Я тестував це лише в Rails 4, але є цікавий спосіб використовувати діапазон з where
хешем, щоб отримати таку поведінку.
User.where(id: 201..Float::INFINITY)
буде генерувати SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
Те ж можна зробити і менше, ніж з -Float::INFINITY
.
Я щойно розмістив подібне запитання про те, щоб зробити це з датами тут, на SO .
>=
проти >
Щоб уникнути людей, котрі перекопуються та слідкують за розмовою з коментарями, тут є основні моменти.
Наведений вище метод генерує лише >=
запит, а не a >
. Існує багато способів впоратися з цією альтернативою.
Для дискретних чисел
Ви можете використовувати number_you_want + 1
стратегію на зразок вище, де мене цікавлять Користувачі, id > 200
але насправді шукаю id >= 201
. Це добре для цілих чисел і чисел, де можна збільшити на одну одиницю інтересу.
Якщо у вас є число, вилучене в константу з назвою добре, це може бути найпростіше прочитати і зрозуміти з першого погляду.
Перевернута логіка
Ми можемо використовувати те, що x > y == !(x <= y)
і використовувати ланцюг, де не.
User.where.not(id: -Float::INFINITY..200)
який генерує SQL
SELECT `users`.* FROM `users` WHERE (NOT (`users`.`id` <= 200))
Це потребує додаткової секунди для читання та обґрунтування, але вона буде працювати для не дискретних значень або стовпців, де ви не можете використовувати + 1
стратегію.
Арел таблиці
Якщо ви хочете пофантазувати, ви можете скористатися Arel::Table
.
User.where(User.arel_table[:id].gt(200))
буде генерувати SQL
"SELECT `users`.* FROM `users` WHERE (`users`.`id` > 200)"
Специфіка така:
User.arel_table #=> an Arel::Table instance for the User model / users table
User.arel_table[:id] #=> an Arel::Attributes::Attribute for the id column
User.arel_table[:id].gt(200) #=> an Arel::Nodes::GreaterThan which can be passed to `where`
Цей підхід дозволить отримати точний SQL, який вас цікавить, проте не багато людей використовують таблицю Arel безпосередньо, і вони можуть вважати її брудною та / або заплутаною. Ви та ваша команда будете знати, що найкраще для вас.
Починаючи з Rails 5, ви також можете зробити це з датами!
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
буде генерувати SQL
SELECT `users`.* FROM `users` WHERE (`users`.`created_at` >= '2018-07-07 17:00:51')
Після виходу Ruby 2.6 (25 грудня 2018 року) ви зможете використовувати новий синтаксис нескінченного діапазону! Замість цього 201..Float::INFINITY
ви зможете просто писати 201..
. Більше інформації в цій публікації в блозі .
where
. Бо >
я пропоную використовувати >= (number_you_want + 1)
для простоти. Якщо ви дійсно хочете переконатися, що це лише >
запит, ви можете отримати доступ до таблиці ARel. Кожен клас, який успадковує, ActiveRecord
має arel_table
метод getter, який повертає Arel::Table
для цього класу. До стовпців таблиці можна отримати такий []
спосіб User.arel_table[:id]
. Це повертає Arel::Attributes::Attribute
дзвінок, gt
на який можна зателефонувати та перейти 200
. Потім це можна передати where
. напр User.where(User.arel_table[:id].gt(200))
.
User.where(created_at: 3.days.ago..DateTime::Infinity.new)
.
WHERE (users.created_at >= '2016-04-09 14:31:15' AND users.created_at < #<Date::Infinity:0x00>)
(задні тики навколо таблиці та назви стовпців пропущені для форматування коментарів SO).
Якщо ви хочете більш інтуїтивно писати, у вас є дорогоцінний камінь, який називається скрип, який дозволить вам написати свою інструкцію так:
User.where{id > 200}
Зверніть увагу на символи "дужки" {} і id
це лише текст.
Все, що вам потрібно зробити - це додати скрип до вашого Gemfile:
gem "squeel"
Це може значно полегшити ваше життя, коли ви пишете складний SQL-заяву в Ruby.
Ще одна фантазія:
User.where("id > :id", id: 100)
Ця функція дозволяє створювати більш зрозумілі запити, якщо ви хочете замінити їх у кількох місцях, наприклад ...
User.where("id > :id OR number > :number AND employee_id = :employee", id: 100, number: 102, employee: 1205)
Це має більше значення, ніж багато ?
в запиті ...
User.where("id > ? OR number > ? AND employee_id = ?", 100, 102, 1205)
У мене часто виникають проблеми з полями дат (де оператори порівняння дуже поширені).
Детальніше розкрити відповідь Міхай, яка, на мою думку, є надійним підходом.
До моделей ви можете додати такі сфери застосування:
scope :updated_at_less_than, -> (date_param) {
where(arel_table[:updated_at].lt(date_param)) }
... а потім у контролері чи де ви використовуєте свою модель:
result = MyModel.updated_at_less_than('01/01/2017')
... складніший приклад з приєднаннями виглядає так:
result = MyParentModel.joins(:my_model).
merge(MyModel.updated_at_less_than('01/01/2017'))
Величезною перевагою такого підходу є: (а) він дозволяє складати запити з різних областей і (b) уникає зіткнень з псевдонімом, коли ви двічі приєднуєтесь до однієї таблиці, оскільки arel_table буде обробляти цю частину генерації запитів.
Rails 6.1 додав новий "синтаксис" для операторів порівняння в where
умовах, наприклад:
Post.where('id >': 9)
Post.where('id >=': 9)
Post.where('id <': 3)
Post.where('id <=': 3)
Тож ваш запит можна переписати так:
User.where('id >': 200)
Ось посилання на PR, де ви можете знайти більше прикладів.
Коротше:
User.where("id > 200")
where("id > ?", 200)
синтаксис). Цього не досягти.