Rails ActiveRecord - 通过匹配号码进行订单查询
Rails ActiveRecord - Order query by matching number
我有一个名为 Location
的模型。这个 table 有 2 个我想按以下顺序排序的字段:rating
(整数)和 name
(字符串)。
我想按名字的字母顺序排序,但如果评级是 5,我希望该评级排在第一位。如果评级是除 5 以外的任何其他评级,我希望它们在 5 之后按字母顺序公正地显示。
这可能与 SQL 有关吗?我知道我显然可以使用 Ruby 的 Array#sort 做到这一点,但我想将其作为查询来做到这一点。
是的,你可以用一点 SQL 来做到这一点。您需要在 ORDER BY:
中包含一个 case
表达式
case rating when 5 then 0 else 1 end
这大致相当于 Ruby 中的 rating == 5 ? 0 : 1
,因此它会将所有评级为 5 的位置放在第一位,然后是其他位置。然后按 name
:
排序
Location.order(Arel.sql('case rating when 5 then 0 else 1 end, name'))
当然,您可以将其隐藏在一个范围内,以便于阅读和理解。
您可以使用 window 函数 ROW_NUMBER 为每个排名分配一个“序列”值。然后为该“序列”应用带有附加谓词的 case 语句以满足您的限制。
select rank,name
from ( select rank, name
, row_number() over (partition by rank
order by rank, name ) rn
from location
) l
order by case when rank=5 and rn<=3 then 0 else 1 end
, name;
我有一个名为 Location
的模型。这个 table 有 2 个我想按以下顺序排序的字段:rating
(整数)和 name
(字符串)。
我想按名字的字母顺序排序,但如果评级是 5,我希望该评级排在第一位。如果评级是除 5 以外的任何其他评级,我希望它们在 5 之后按字母顺序公正地显示。
这可能与 SQL 有关吗?我知道我显然可以使用 Ruby 的 Array#sort 做到这一点,但我想将其作为查询来做到这一点。
是的,你可以用一点 SQL 来做到这一点。您需要在 ORDER BY:
中包含一个case
表达式
case rating when 5 then 0 else 1 end
这大致相当于 Ruby 中的 rating == 5 ? 0 : 1
,因此它会将所有评级为 5 的位置放在第一位,然后是其他位置。然后按 name
:
Location.order(Arel.sql('case rating when 5 then 0 else 1 end, name'))
当然,您可以将其隐藏在一个范围内,以便于阅读和理解。
您可以使用 window 函数 ROW_NUMBER 为每个排名分配一个“序列”值。然后为该“序列”应用带有附加谓词的 case 语句以满足您的限制。
select rank,name
from ( select rank, name
, row_number() over (partition by rank
order by rank, name ) rn
from location
) l
order by case when rank=5 and rn<=3 then 0 else 1 end
, name;