Ruby on Rails: ฉันจะจัดเรียงสองคอลัมน์โดยใช้ ActiveRecord ได้อย่างไร


94

ฉันต้องการจัดเรียงตามสองคอลัมน์หนึ่งคือ DateTime ( updated_at) และอีกคอลัมน์เป็นทศนิยม (ราคา)

ฉันต้องการเรียงลำดับก่อนโดย updated_at จากนั้นหากมีหลายรายการเกิดขึ้นในวันเดียวกันให้จัดเรียงตามราคา

คำตอบ:


66

สมมติว่าคุณใช้ MySQL

Model.all(:order => 'DATE(updated_at), price')

สังเกตความแตกต่างจากคำตอบอื่น ๆ updated_atคอลัมน์จะมีการประทับเวลาเต็มรูปแบบดังนั้นหากคุณต้องการเรียงลำดับขึ้นอยู่กับวันที่มันได้รับการปรับปรุงคุณต้องใช้ฟังก์ชั่นที่จะได้รับเพียงส่วนหนึ่งวันจากการประทับเวลา ใน MySQL, DATE()ที่อยู่


7
หากต้องการหยุดการรวมจากข้อความ "คอลัมน์ที่ไม่ชัดเจน" แบบสุ่มคุณควรใช้เวอร์ชันที่มีประสิทธิภาพมากขึ้นต่อไปนี้: :order => ["DATE(#{table_name}.updated_at)", :price](โปรดทราบว่า:priceเป็นสัญลักษณ์)
Jo Liss

ฉันต้องหนีคอลัมน์คำสั่งของฉันด้วยorderสิ่งนี้:Model.all(:order => "day asc, `order` asc")
ให้สิทธิ์

149

ใน Rails 4 คุณสามารถทำสิ่งที่คล้ายกับ:

Model.order(foo: :asc, bar: :desc)

fooและbarเป็นคอลัมน์ในฐานข้อมูล


1
Rails 4 นั้นยิ่งใหญ่ที่สุด
Darth Egregious

57
Thing.find(:all, :order => "updated_at desc, price asc")

จะทำเคล็ดลับ

อัปเดต:

Thing.all.order("updated_at DESC, price ASC")

คือทางรถไฟ 3 ทางที่จะไป (ขอบคุณ@cpursley )


4
ขอบคุณ @Erik - ฉันรู้ว่าคำตอบนี้เก่าดังนั้นนี่คือคำเตือนของฉันสำหรับผู้ที่เห็นตอนนี้: วิธีนี้เลิกใช้แล้วตั้งแต่ Rails 3.2 ใช้ Thing.all แทน =)
Abdo

ถูกต้องสิ่งนี้ใช้ได้ดีสำหรับฉัน: Thing.all.order("updated_at DESC, price ASC")
cpursley

1
Thing.order("LOWER(name), number")อัปเดตของคุณเป็นประโยชน์สำหรับฉันเมื่อฉันต้องการที่จะเป็นตัวพิมพ์เล็กค่าเรียง:
นิค

36

Active Record Query Interfaceช่วยให้คุณระบุแอตทริบิวต์ได้มากเท่าที่คุณต้องการสั่งซื้อ :

models = Model.order(:date, :hour, price: :desc)

หรือหากต้องการเจาะจงมากขึ้น (ขอบคุณ@ zw963 ):

models = Model.order(price: :desc, date: :desc, price: :asc) 

โบนัส: หลังจากการค้นหาครั้งแรกคุณสามารถเชื่อมโยงการค้นหาอื่น ๆ ได้:

models = models.where('date >= :date', date: Time.current.to_date)

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ฉันขอเปลี่ยนเป็นการส่วนตัวmodelเพื่อmodelsให้คนรู้ว่ามันเป็นพหูพจน์ เพียงข้อเสนอแนะ
ทัศ

1
ฉันคิดว่าควรแก้ไขตัวอย่างที่พิเศษกว่านี้เช่น models = Model.order ({price:: desc}, {date:: desc}, {price: asc})
zw963

หากใครวางสิ่งนี้และเห็นข้อผิดพลาดของวิธีการที่ไม่ได้กำหนดจะมีการพิมพ์ผิดเล็กน้อยที่นี่ ควรจะ:ascแทนasc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
nayiaw

18

จริงๆแล้วมีหลายวิธีที่จะทำได้โดยใช้ Active Record สิ่งที่ไม่ได้กล่าวถึงข้างต้นจะเป็น (ในรูปแบบต่างๆใช้ได้ทั้งหมด):

Model.order(foo: :asc).order(:bar => :desc).order(:etc)

อาจจะดูละเอียดกว่า แต่โดยส่วนตัวแล้วฉันคิดว่ามันง่ายต่อการจัดการ SQL สร้างขึ้นในขั้นตอนเดียวเท่านั้น:

SELECT "models".* FROM "models" ORDER BY "models"."etc" ASC, "models"."bar" DESC, "models"."foo" ASC

ดังนั้นสำหรับคำถามเดิม:

Model.order(:updated_at).order(:price)

คุณไม่จำเป็นต้องประกาศประเภทข้อมูล ActiveRecord ก็ทำได้อย่างราบรื่นและ DB Engine ของคุณก็เช่นกัน


วิธีนี้ใช้งานได้ดีเมื่อใช้สองคอลัมน์จากสองตารางที่แตกต่างกันเช่น Member.includes (: voter) .order ("town_club asc"). order ("voters.last_name asc")
bkunzi01

1
SQL ที่คุณโพสต์สอดคล้องModel.order(foo: :asc).order(:bar => :desc).order(:etc)หรือไม่ ลำดับของคำสั่งคำสั่งใน SQL เป็นตรงกันข้ามกับสิ่งที่ฉันได้รับเมื่อฉันเรียกใช้.to_sqlว่า
Qaz

1
@Qaz นี่นานแล้ว ฉันคิดว่าฉันอาจต้องแก้ไขข้อนี้ฉันไม่เคยสังเกตเห็น ฉันจะตรวจสอบอีกครั้งในภายหลัง ขอบคุณ.
Ruby Racer


0

สิ่งเหล่านี้ไม่ได้ผลสำหรับฉัน! หลังจากมองบนและล่างผ่านอินเทอร์เน็ตเพียง 2 วันก็พบวิธีแก้ปัญหา !!

สมมติว่าคุณมีคอลัมน์มากมายในตารางผลิตภัณฑ์ ได้แก่ special_price และ msrp นี่คือสองคอลัมน์ที่เราพยายามจัดเรียงด้วย

เอาล่ะอันดับแรกในโมเดลของคุณให้เพิ่มบรรทัดนี้:

named_scope :sorted_by_special_price_asc_msrp_asc, { :order => 'special_price asc,msrp asc' }

ประการที่สองใน Product Controller ให้เพิ่มตำแหน่งที่คุณต้องทำการค้นหา:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.