ActiveRecord .last和ActiveRecord .last(1)返回不同的结果

时间:2015-02-23 16:37:13

标签: mysql ruby-on-rails ruby activerecord

将ActiveRecord 4.2与MySQL 5.5一起使用

我有一个名为Product的模型。

在控制台中运行Product.last - 我在表格中获得了第一条记录(2013年为id 1和updated_at)

正在运行Product.last(1) - 我在2015年2月的id(122039)和updated_at表中获得了最新记录。

我的印象是他们应该返回相同的。为什么Product.last会返回Product.first的结果?

P.S .: 这是一个开发数据库。所以我将其销毁并重新迁移并重新播种所有数据。不知道它是否重要,但是为了加快播种过程(因为我在一些桌子上播放了10万行的生产级数据) - 我使用批量插入和放大来自.sql文件。 ActiveRecord::Base.connection.execute(sql_from_file)

更新

进行了比较(参见下面的2个编辑),似乎Product.last不执行order by id desc,而Product.last(1)实际执行此操作。有什么想法吗?

编辑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 

vs second 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)

**编辑2 **

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

2 个答案:

答案 0 :(得分:1)

ActiveRecord的#first#last没有任何默示订单,只需要您的数据库即可完成。

在大多数情况下,它们将按主键顺序返回,但并非总是如此。

最好在您真正需要时明确说明您的订单。

答案 1 :(得分:0)

罪魁祸首是我的模型中的eager_loading。

好的,似乎需要记住一些事情,可能会在文档中提到,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 - 在第一种情况下搞砸了。