ฉันพยายามค้นหาผู้ใช้ทั้งหมดที่มี ID มากกว่า 200 แต่ฉันมีปัญหากับไวยากรณ์เฉพาะบางอย่าง
User.where(:id > 200)
และ
User.where("? > 200", :id)
มีทั้งล้มเหลว
ข้อเสนอแนะใด ๆ
ฉันพยายามค้นหาผู้ใช้ทั้งหมดที่มี ID มากกว่า 200 แต่ฉันมีปัญหากับไวยากรณ์เฉพาะบางอย่าง
User.where(:id > 200)
และ
User.where("? > 200", :id)
มีทั้งล้มเหลว
ข้อเสนอแนะใด ๆ
คำตอบ:
ลองสิ่งนี้
User.where("id > ?", 200)
?
มากกว่าการใส่ inline 200
หรือไม่?
ฉันเพิ่งทดสอบสิ่งนี้ใน Rails 4 แต่มีวิธีที่น่าสนใจในการใช้ช่วงที่มีwhere
แฮชเพื่อให้ได้พฤติกรรมนี้
User.where(id: 201..Float::INFINITY)
จะสร้าง SQL
SELECT `users`.* FROM `users` WHERE (`users`.`id` >= 201)
-Float::INFINITY
เช่นเดียวกับที่สามารถทำได้น้อยกว่าด้วย
ฉันเพียงแค่โพสต์คำถามที่คล้ายกันถามเกี่ยวกับการทำเช่นนี้กับวันที่นี่ใน SO
>=
VS >
เพื่อหลีกเลี่ยงคนที่ต้องขุดและติดตามการสนทนาความคิดเห็นที่นี่เป็นไฮไลท์
วิธีการดังกล่าวเพียง แต่สร้าง>=
แบบสอบถามและไม่ >
มีหลายวิธีในการจัดการทางเลือกนี้
สำหรับตัวเลขที่ไม่ต่อเนื่อง
คุณสามารถใช้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
matchers สำหรับ>
ฉันขอแนะนำให้ใช้>= (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)
การใช้งานที่ดีกว่าคือการสร้างขอบเขตในโมเดลผู้ใช้ where(arel_table[:id].gt(id))
หากคุณต้องการการเขียนที่เข้าใจง่ายยิ่งขึ้นมันมีอัญมณีที่เรียกว่าsqueelที่จะช่วยให้คุณเขียนคำสั่งของคุณเช่นนี้:
User.where{id > 200}
สังเกตว่าอักขระ 'วงเล็บปีกกา' {} และid
เป็นเพียงข้อความ
สิ่งที่คุณต้องทำคือเพิ่ม squeel ให้กับ Gemfile ของคุณ:
gem "squeel"
สิ่งนี้อาจทำให้ชีวิตคุณง่ายขึ้นมากเมื่อเขียนคำสั่ง SQL ที่ซับซ้อนใน Ruby
Arel เป็นเพื่อนของคุณ
User.where (User.arel_table [: ID] .gt (200))
ความเป็นไปได้ที่น่าสนใจอีกอย่างคือ ...
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)
ฉันมักจะมีปัญหานี้กับเขตข้อมูลวันที่ (ที่ตัวดำเนินการเปรียบเทียบทั่วไปมาก)
เพื่ออธิบายเพิ่มเติมเกี่ยวกับคำตอบของ Mihai ซึ่งฉันเชื่อว่าเป็นแนวทางที่มั่นคง
สำหรับโมเดลคุณสามารถเพิ่มขอบเขตดังนี้:
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'))
ข้อได้เปรียบอย่างมากของวิธีนี้คือ (a) ช่วยให้คุณสามารถเขียนแบบสอบถามจากขอบเขตที่แตกต่างกันและ (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)
แบบใช้พารามิเตอร์ ( ไวยากรณ์) สิ่งนี้ไม่ประสบความสำเร็จ