2015-02-23 4 views
1

Использование ActiveRecord 4.2 с MySQL 5.5ActiveRecord .last и ActiveRecord .last (1) различные результаты

У меня есть модель под названием продукта.

Запуск Product.last в консоли - я получаю первую запись в таблице (с идентификатором 1 и updated_at в 2013 году)

Запуск Product.last(1) - я получаю последнюю запись в таблице с идентификатором (122039) и updated_at в феврале 2015.

У меня сложилось впечатление, что они должны вернуть то же самое. Почему бы Product.last вернуть результат Product.first?

P.S .: Это база данных разработчиков. Поэтому я уничтожил его и перепрофилировал и повторно засеял все данные. Не знаю, если это имеет значение, но для ускорения процессов высева (так как я семена некоторых таблиц с 100,000s строк данных производственно-класс) - I семян из .sql файлов с помощью массовой вставки & ActiveRecord::Base.connection.execute(sql_from_file)

UPDATE

Проведя сравнение (см. 2 правки ниже), похоже, что Product.last не делает order by id desc, в то время как Product.last (1) делает это на самом деле. Любые идеи почему?

EDIT 1 Из журналов:

Product.last (1)

SELECT DISTINCT 
    `products`.`id` 
FROM 
    `products` 
    LEFT OUTER JOIN `restrictions` 
    ON `restrictions`.`id` = `products`.`distribution_restriction_id` 
    AND `restrictions`.`type` IN ('DistributionRestriction') 
    LEFT OUTER JOIN `vendors` 
    ON `vendors`.`id` = `products`.`vendor_id` 
    LEFT OUTER JOIN `manufacturers` 
    ON `manufacturers`.`id` = `products`.`manufacturer_id` 
    LEFT OUTER JOIN `categories` 
    ON `categories`.`id` = `products`.`category_id` 
    AND `categories`.`type` IN ('ProductCategory') 
    LEFT OUTER JOIN `products_restrictions` 
    ON `products_restrictions`.`product_id` = `products`.`id` 
    LEFT OUTER JOIN `restrictions` `restrictions_products` 
    ON `restrictions_products`.`id` = `products_restrictions`.`restriction_id` 
    AND `restrictions_products`.`type` IN ('ProductRestriction') 
    LEFT OUTER JOIN `categories` `departments_products` 
    ON `departments_products`.`id` = `products`.`department_id` 
    AND `departments_products`.`type` IN ('Department') 
    LEFT OUTER JOIN `comments` 
    ON `comments`.`commentable_id` = `products`.`id` 
    AND `comments`.`commentable_type` = 'Product' 
    LEFT OUTER JOIN `pictures` 
    ON `pictures`.`picturable_id` = `products`.`id` 
    AND `pictures`.`picturable_type` = 'Product' 
ORDER BY `products`.`id` DESC 
LIMIT 1 ; 

SELECT 
    `products`.`id` AS t0_r0, 
    `products`.`name` AS t0_r1, 
    `products`.`client_number` AS t0_r2, 
    `products`.`client_reference_string` AS t0_r3, 
    `products`.`client_id` AS t0_r4, 
    `products`.`vendor_number` AS t0_r5, 
    `products`.`vendor_reference_string` AS t0_r6, 
    `products`.`vendor_id` AS t0_r7, 
    `products`.`manufacturer_number` AS t0_r8, 
    `products`.`manufacturer_reference_string` AS t0_r9, 
    `products`.`manufacturer_id` AS t0_r10, 
    `products`.`reman_number` AS t0_r11, 
    `products`.`superseded_by_id` AS t0_r12, 
    `products`.`description` AS t0_r13, 
    `products`.`category_id` AS t0_r14, 
    `products`.`first_year_used` AS t0_r15, 
    `products`.`last_year_used` AS t0_r16, 
    `products`.`reorder_level` AS t0_r17, 
    `products`.`minimum_order_quantity` AS t0_r18, 
    `products`.`total_stock` AS t0_r19, 
    `products`.`stock_details` AS t0_r20, 
    `products`.`status` AS t0_r21, 
    `products`.`discontinued_at` AS t0_r22, 
    `products`.`currency` AS t0_r23, 
    `products`.`dealer_exchange_amount_cents` AS t0_r24, 
    `products`.`dealer_sale_amount_cents` AS t0_r25, 
    `products`.`retail_exchange_amount_cents` AS t0_r26, 
    `products`.`retail_sale_amount_cents` AS t0_r27, 
    `products`.`cost_amount_cents` AS t0_r28, 
    `products`.`core_charge_amount_cents` AS t0_r29, 
    `products`.`reman_amount_cents` AS t0_r30, 
    `products`.`out_of_warranty` AS t0_r31, 
    `products`.`backordered_till` AS t0_r32, 
    `products`.`repair_only` AS t0_r33, 
    `products`.`publicly_visible` AS t0_r34, 
    `products`.`period_usage` AS t0_r35, 
    `products`.`distribution_restriction_id` AS t0_r36, 
    `products`.`department_id` AS t0_r37, 
    `products`.`stats` AS t0_r38, 
    `products`.`announcement_date` AS t0_r39, 
    `products`.`status_with_vendor` AS t0_r40, 
    `products`.`masterfile_details` AS t0_r41, 
    `products`.`created_at` AS t0_r42, 
    `products`.`updated_at` AS t0_r43, 
    `restrictions`.`id` AS t1_r0, 
    `restrictions`.`name` AS t1_r1, 
    `restrictions`.`code` AS t1_r2, 
    `restrictions`.`description` AS t1_r3, 
    `restrictions`.`severity` AS t1_r4, 
    `restrictions`.`begins_at` AS t1_r5, 
    `restrictions`.`expires_at` AS t1_r6, 
    `restrictions`.`type` AS t1_r7, 
    `restrictions`.`created_at` AS t1_r8, 
    `restrictions`.`updated_at` AS t1_r9, 
    `vendors`.`id` AS t2_r0, 
    `vendors`.`name` AS t2_r1, 
    `vendors`.`code` AS t2_r2, 
    `vendors`.`created_at` AS t2_r3, 
    `vendors`.`updated_at` AS t2_r4, 
    `manufacturers`.`id` AS t3_r0, 
    `manufacturers`.`name` AS t3_r1, 
    `manufacturers`.`code` AS t3_r2, 
    `manufacturers`.`created_at` AS t3_r3, 
    `manufacturers`.`updated_at` AS t3_r4, 
    `categories`.`id` AS t4_r0, 
    `categories`.`name` AS t4_r1, 
    `categories`.`code` AS t4_r2, 
    `categories`.`description` AS t4_r3, 
    `categories`.`type` AS t4_r4, 
    `categories`.`category_id` AS t4_r5, 
    `categories`.`created_at` AS t4_r6, 
    `categories`.`updated_at` AS t4_r7, 
    `restrictions_products`.`id` AS t5_r0, 
    `restrictions_products`.`name` AS t5_r1, 
    `restrictions_products`.`code` AS t5_r2, 
    `restrictions_products`.`description` AS t5_r3, 
    `restrictions_products`.`severity` AS t5_r4, 
    `restrictions_products`.`begins_at` AS t5_r5, 
    `restrictions_products`.`expires_at` AS t5_r6, 
    `restrictions_products`.`type` AS t5_r7, 
    `restrictions_products`.`created_at` AS t5_r8, 
    `restrictions_products`.`updated_at` AS t5_r9, 
    `departments_products`.`id` AS t6_r0, 
    `departments_products`.`name` AS t6_r1, 
    `departments_products`.`code` AS t6_r2, 
    `departments_products`.`description` AS t6_r3, 
    `departments_products`.`type` AS t6_r4, 
    `departments_products`.`category_id` AS t6_r5, 
    `departments_products`.`created_at` AS t6_r6, 
    `departments_products`.`updated_at` AS t6_r7, 
    `comments`.`id` AS t7_r0, 
    `comments`.`title` AS t7_r1, 
    `comments`.`body` AS t7_r2, 
    `comments`.`author_id` AS t7_r3, 
    `comments`.`category` AS t7_r4, 
    `comments`.`commentable_id` AS t7_r5, 
    `comments`.`commentable_type` AS t7_r6, 
    `comments`.`created_at` AS t7_r7, 
    `comments`.`updated_at` AS t7_r8, 
    `pictures`.`id` AS t8_r0, 
    `pictures`.`name` AS t8_r1, 
    `pictures`.`title` AS t8_r2, 
    `pictures`.`path` AS t8_r3, 
    `pictures`.`picturable_id` AS t8_r4, 
    `pictures`.`picturable_type` AS t8_r5, 
    `pictures`.`category` AS t8_r6, 
    `pictures`.`created_at` AS t8_r7, 
    `pictures`.`updated_at` AS t8_r8 
FROM 
    `products` 
    LEFT OUTER JOIN `restrictions` 
    ON `restrictions`.`id` = `products`.`distribution_restriction_id` 
    AND `restrictions`.`type` IN ('DistributionRestriction') 
    LEFT OUTER JOIN `vendors` 
    ON `vendors`.`id` = `products`.`vendor_id` 
    LEFT OUTER JOIN `manufacturers` 
    ON `manufacturers`.`id` = `products`.`manufacturer_id` 
    LEFT OUTER JOIN `categories` 
    ON `categories`.`id` = `products`.`category_id` 
    AND `categories`.`type` IN ('ProductCategory') 
    LEFT OUTER JOIN `products_restrictions` 
    ON `products_restrictions`.`product_id` = `products`.`id` 
    LEFT OUTER JOIN `restrictions` `restrictions_products` 
    ON `restrictions_products`.`id` = `products_restrictions`.`restriction_id` 
    AND `restrictions_products`.`type` IN ('ProductRestriction') 
    LEFT OUTER JOIN `categories` `departments_products` 
    ON `departments_products`.`id` = `products`.`department_id` 
    AND `departments_products`.`type` IN ('Department') 
    LEFT OUTER JOIN `comments` 
    ON `comments`.`commentable_id` = `products`.`id` 
    AND `comments`.`commentable_type` = 'Product' 
    LEFT OUTER JOIN `pictures` 
    ON `pictures`.`picturable_id` = `products`.`id` 
    AND `pictures`.`picturable_type` = 'Product' 
WHERE `products`.`id` IN (122039) 
ORDER BY `products`.`id` DESC 

против второго Product.last

SQL (2.1 ms) 
SELECT DISTINCT 
    `products`.`id` 
FROM 
    `products` 
    LEFT OUTER JOIN `restrictions` 
    ON `restrictions`.`id` = `products`.`distribution_restriction_id` 
    AND `restrictions`.`type` IN ('DistributionRestriction') 
    LEFT OUTER JOIN `vendors` 
    ON `vendors`.`id` = `products`.`vendor_id` 
    LEFT OUTER JOIN `manufacturers` 
    ON `manufacturers`.`id` = `products`.`manufacturer_id` 
    LEFT OUTER JOIN `categories` 
    ON `categories`.`id` = `products`.`category_id` 
    AND `categories`.`type` IN ('ProductCategory') 
    LEFT OUTER JOIN `products_restrictions` 
    ON `products_restrictions`.`product_id` = `products`.`id` 
    LEFT OUTER JOIN `restrictions` `restrictions_products` 
    ON `restrictions_products`.`id` = `products_restrictions`.`restriction_id` 
    AND `restrictions_products`.`type` IN ('ProductRestriction') 
    LEFT OUTER JOIN `categories` `departments_products` 
    ON `departments_products`.`id` = `products`.`department_id` 
    AND `departments_products`.`type` IN ('Department') 
    LEFT OUTER JOIN `comments` 
    ON `comments`.`commentable_id` = `products`.`id` 
    AND `comments`.`commentable_type` = 'Product' 
    LEFT OUTER JOIN `pictures` 
    ON `pictures`.`picturable_id` = `products`.`id` 
    AND `pictures`.`picturable_type` = 'Product' 
LIMIT 1 ; 

SELECT 
    `products`.`id` AS t0_r0, 
    `products`.`name` AS t0_r1, 
    `products`.`client_number` AS t0_r2, 
    `products`.`client_reference_string` AS t0_r3, 
    `products`.`client_id` AS t0_r4, 
    `products`.`vendor_number` AS t0_r5, 
    `products`.`vendor_reference_string` AS t0_r6, 
    `products`.`vendor_id` AS t0_r7, 
    `products`.`manufacturer_number` AS t0_r8, 
    `products`.`manufacturer_reference_string` AS t0_r9, 
    `products`.`manufacturer_id` AS t0_r10, 
    `products`.`reman_number` AS t0_r11, 
    `products`.`superseded_by_id` AS t0_r12, 
    `products`.`description` AS t0_r13, 
    `products`.`category_id` AS t0_r14, 
    `products`.`first_year_used` AS t0_r15, 
    `products`.`last_year_used` AS t0_r16, 
    `products`.`reorder_level` AS t0_r17, 
    `products`.`minimum_order_quantity` AS t0_r18, 
    `products`.`total_stock` AS t0_r19, 
    `products`.`stock_details` AS t0_r20, 
    `products`.`status` AS t0_r21, 
    `products`.`discontinued_at` AS t0_r22, 
    `products`.`currency` AS t0_r23, 
    `products`.`dealer_exchange_amount_cents` AS t0_r24, 
    `products`.`dealer_sale_amount_cents` AS t0_r25, 
    `products`.`retail_exchange_amount_cents` AS t0_r26, 
    `products`.`retail_sale_amount_cents` AS t0_r27, 
    `products`.`cost_amount_cents` AS t0_r28, 
    `products`.`core_charge_amount_cents` AS t0_r29, 
    `products`.`reman_amount_cents` AS t0_r30, 
    `products`.`out_of_warranty` AS t0_r31, 
    `products`.`backordered_till` AS t0_r32, 
    `products`.`repair_only` AS t0_r33, 
    `products`.`publicly_visible` AS t0_r34, 
    `products`.`period_usage` AS t0_r35, 
    `products`.`distribution_restriction_id` AS t0_r36, 
    `products`.`department_id` AS t0_r37, 
    `products`.`stats` AS t0_r38, 
    `products`.`announcement_date` AS t0_r39, 
    `products`.`status_with_vendor` AS t0_r40, 
    `products`.`masterfile_details` AS t0_r41, 
    `products`.`created_at` AS t0_r42, 
    `products`.`updated_at` AS t0_r43, 
    `restrictions`.`id` AS t1_r0, 
    `restrictions`.`name` AS t1_r1, 
    `restrictions`.`code` AS t1_r2, 
    `restrictions`.`description` AS t1_r3, 
    `restrictions`.`severity` AS t1_r4, 
    `restrictions`.`begins_at` AS t1_r5, 
    `restrictions`.`expires_at` AS t1_r6, 
    `restrictions`.`type` AS t1_r7, 
    `restrictions`.`created_at` AS t1_r8, 
    `restrictions`.`updated_at` AS t1_r9, 
    `vendors`.`id` AS t2_r0, 
    `vendors`.`name` AS t2_r1, 
    `vendors`.`code` AS t2_r2, 
    `vendors`.`created_at` AS t2_r3, 
    `vendors`.`updated_at` AS t2_r4, 
    `manufacturers`.`id` AS t3_r0, 
    `manufacturers`.`name` AS t3_r1, 
    `manufacturers`.`code` AS t3_r2, 
    `manufacturers`.`created_at` AS t3_r3, 
    `manufacturers`.`updated_at` AS t3_r4, 
    `categories`.`id` AS t4_r0, 
    `categories`.`name` AS t4_r1, 
    `categories`.`code` AS t4_r2, 
    `categories`.`description` AS t4_r3, 
    `categories`.`type` AS t4_r4, 
    `categories`.`category_id` AS t4_r5, 
    `categories`.`created_at` AS t4_r6, 
    `categories`.`updated_at` AS t4_r7, 
    `restrictions_products`.`id` AS t5_r0, 
    `restrictions_products`.`name` AS t5_r1, 
    `restrictions_products`.`code` AS t5_r2, 
    `restrictions_products`.`description` AS t5_r3, 
    `restrictions_products`.`severity` AS t5_r4, 
    `restrictions_products`.`begins_at` AS t5_r5, 
    `restrictions_products`.`expires_at` AS t5_r6, 
    `restrictions_products`.`type` AS t5_r7, 
    `restrictions_products`.`created_at` AS t5_r8, 
    `restrictions_products`.`updated_at` AS t5_r9, 
    `departments_products`.`id` AS t6_r0, 
    `departments_products`.`name` AS t6_r1, 
    `departments_products`.`code` AS t6_r2, 
    `departments_products`.`description` AS t6_r3, 
    `departments_products`.`type` AS t6_r4, 
    `departments_products`.`category_id` AS t6_r5, 
    `departments_products`.`created_at` AS t6_r6, 
    `departments_products`.`updated_at` AS t6_r7, 
    `comments`.`id` AS t7_r0, 
    `comments`.`title` AS t7_r1, 
    `comments`.`body` AS t7_r2, 
    `comments`.`author_id` AS t7_r3, 
    `comments`.`category` AS t7_r4, 
    `comments`.`commentable_id` AS t7_r5, 
    `comments`.`commentable_type` AS t7_r6, 
    `comments`.`created_at` AS t7_r7, 
    `comments`.`updated_at` AS t7_r8, 
    `pictures`.`id` AS t8_r0, 
    `pictures`.`name` AS t8_r1, 
    `pictures`.`title` AS t8_r2, 
    `pictures`.`path` AS t8_r3, 
    `pictures`.`picturable_id` AS t8_r4, 
    `pictures`.`picturable_type` AS t8_r5, 
    `pictures`.`category` AS t8_r6, 
    `pictures`.`created_at` AS t8_r7, 
    `pictures`.`updated_at` AS t8_r8 
FROM 
    `products` 
    LEFT OUTER JOIN `restrictions` 
    ON `restrictions`.`id` = `products`.`distribution_restriction_id` 
    AND `restrictions`.`type` IN ('DistributionRestriction') 
    LEFT OUTER JOIN `vendors` 
    ON `vendors`.`id` = `products`.`vendor_id` 
    LEFT OUTER JOIN `manufacturers` 
    ON `manufacturers`.`id` = `products`.`manufacturer_id` 
    LEFT OUTER JOIN `categories` 
    ON `categories`.`id` = `products`.`category_id` 
    AND `categories`.`type` IN ('ProductCategory') 
    LEFT OUTER JOIN `products_restrictions` 
    ON `products_restrictions`.`product_id` = `products`.`id` 
    LEFT OUTER JOIN `restrictions` `restrictions_products` 
    ON `restrictions_products`.`id` = `products_restrictions`.`restriction_id` 
    AND `restrictions_products`.`type` IN ('ProductRestriction') 
    LEFT OUTER JOIN `categories` `departments_products` 
    ON `departments_products`.`id` = `products`.`department_id` 
    AND `departments_products`.`type` IN ('Department') 
    LEFT OUTER JOIN `comments` 
    ON `comments`.`commentable_id` = `products`.`id` 
    AND `comments`.`commentable_type` = 'Product' 
    LEFT OUTER JOIN `pictures` 
    ON `pictures`.`picturable_id` = `products`.`id` 
    AND `pictures`.`picturable_type` = 'Product' 
WHERE `products`.`id` IN (1) 

** EDIT 2 **

default_scope {eager_load([:distribution_restriction, :vendor, :manufacturer, :category, :restrictions, :department, :comments, :pictures])} 
+0

Просьба показать SQL из ваших журналов, которые производит каждый оператор. – smathy

+0

Не могли бы вы разместить sql, в результате чего каждый из них? В моем db оба они приводят к 'ORDER BY id DESC' и возвращают те же результаты. Единственное отличие: 'last' возвращает одну запись, а' last (1) 'возвращает массив. – evanbikes

+0

Просто запустите 'ActiveRecord :: Base.logger = Logger.new (STDOUT)', и вы увидите вывод журнала в консоли. – smathy

ответ

0

В моей модели виновен eager_loading.

Ok так что кажется, что это что-то нужно иметь в виду, и, возможно, упоминается в документации, что eager_loading путает порядок в .last()

Я попытался это

scope :include_all, -> {eager_load([:distribution_restriction, :vendor, :manufacturer, :category, :restrictions, :department, :comments, :pictures])}

И затем Product.include_all.last & Product.include_all.last(1)

Как с моей исходной задачей eager_loading - перепутался порядок в фи первый случай.

1

#first ии #last не имеют каких-либо подразумеваемых заказов, и они оставлены до вашей базы данных для выполнения.

В большинстве случаев они возвращаются в порядке первичным ключом, но не всегда.

Лучше быть в курсе вашего заказа, когда вам это действительно нужно.

+0

Не совсем правильно. Из документов: «Найти последнюю запись (или последние N записей, если задан параметр). Если порядок не задан, он будет заказывать по первичному ключу (в этом случае id)». Как я его читал - для меня это означает, что он захватит весь набор (все строки) и вернет последний, основанный на id. У меня есть 30K записей в таблице, но он продолжает возвращать первую запись - с идентификатором 1. Если он не должен возвращать последнюю запись, тогда его следует называть random() :-) – konung

+0

На основе документов - все, что есть equal last() & last (1) должен возвращать то же самое. http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-last – konung

Смежные вопросы