Ruby中如何通过单查询按指定类型顺序排序蛋糕列表?
问题:如何用单条查询实现固定类型顺序+创建时间排序的蛋糕列表?
我有一个@cake.type字段,取值包括"Primo"、"Multilayered"、"Decorative"、"On Sale"、"Basic"。需要按以下固定顺序组织蛋糕列表:先展示所有"Primo"类型蛋糕,接着是"Multilayered"类型,以此类推;每种类型内还要按created_at字段排序(最早创建的排在前面)。
目前我通过多次查询拼接结果的方式实现,代码如下:
@cakes = [] @cakes << @store.cakes.where(type: "Primo").order(created_at: :asc) @cakes << @store.cakes.where(type: "Multilayered").order(created_at: :asc) @cakes << @store.cakes.where(type: "Decorative").order(created_at: :asc) @cakes << @store.cakes.where(type: "On Sale").order(created_at: :asc) @cakes << @store.cakes.where(type: "Basic").order(created_at: :asc)
注:原代码中where(type: "Basic", "Basic")为笔误,已修正为where(type: "Basic")
我还尝试了另一种拼接写法:
cake_eater_nom = [] c = @store.cakes primo_cakes = c.where(type: "Primo").order(created_at: :asc) cake_eater_nom << primo_cakes multilayered_cakes = c.where(type: "Multilayered").order(created_at: :asc) cake_eater_nom << multilayered_cakes decorative_cakes = c.where(type: "Decorative").order(created_at: :asc) cake_eater_nom << decorative_cakes on_sale_cakes = c.where(type: "On Sale").order(created_at: :asc) cake_eater_nom << on_sale_cakes basic_cakes = c.where(type: "Basic").order(created_at: :asc) cake_eater_nom << basic_cakes
请问是否存在通过单条查询实现该排序需求的方法?
解决方案:单条查询实现自定义排序
完全可以通过单条SQL查询实现需求,核心是用CASE语句给每种类型分配固定优先级,再结合created_at排序。不同数据库的实现语法基本一致,以下是几种常见写法:
1. 直接写SQL语句(支持PostgreSQL/MySQL/SQLite)
@cakes = @store.cakes.order( <<~SQL, CASE type WHEN 'Primo' THEN 1 WHEN 'Multilayered' THEN 2 WHEN 'Decorative' THEN 3 WHEN 'On Sale' THEN 4 WHEN 'Basic' THEN 5 ELSE 6 END, created_at ASC SQL )
这里通过CASE给指定类型按需求顺序分配1-5的优先级,优先级数值越小排得越靠前,最后再按created_at升序排列同类型的蛋糕。
2. Rails Arel抽象写法(无需区分数据库)
如果不想直接写原始SQL,可以用Rails的Arel构建排序逻辑,更符合Rails的ORM风格:
type_order = Arel::Case.new .when(Cake.arel_table[:type].eq('Primo')).then(1) .when(Cake.arel_table[:type].eq('Multilayered')).then(2) .when(Cake.arel_table[:type].eq('Decorative')).then(3) .when(Cake.arel_table[:type].eq('On Sale')).then(4) .when(Cake.arel_table[:type].eq('Basic')).then(5) .else(6) @cakes = @store.cakes.order(type_order, created_at: :asc)
两种写法都能实现单条查询获取排序结果,相比多次查询拼接,不仅减少了数据库请求次数,还能利用数据库的排序优化提升性能。
内容的提问来源于stack exchange,提问作者daveasdf
相关产品推荐
相关产品推荐

