按列分组,结果限制并按另一列轨道排序

Posted

技术标签:

【中文标题】按列分组,结果限制并按另一列轨道排序【英文标题】:Group by column, result limit and sort by another column rails 【发布时间】:2022-01-11 20:45:10 【问题描述】:

假设我们有模型ItemStatisticBookItemStatistic示例记录:

  item_id: 15,
  book_id: 3,
  score: 0.25192368e4,

书籍示例:

  id: 3,
  title: 'Harry Potter',

我们需要将ItemStatistic 记录按item_id 分组,然后按score 对每个item_id 键的结果进行排序,并按3 限制每个item_id 键的值的数量并返回not @ 987654332@ 记录但Book。 示例:

15: [id: 3, title: 'Harry Potter', id: 4, title: 'The Chronicles of Narnia',...], 2: [...]

1: [,,], 2: [,,], 3:[,,]

【问题讨论】:

【参考方案1】:

如果我正确理解了这个愿望,以下应该可以工作

item_statistics_table = ItemStatistic.arel_table 
filter = Arel::Table.new('filtered_results')
sub_query = item_statistics_table.project(
  item_statistics[Arel.star],
  Arel.sql('ROW_NUMBER() OVER(
              PARTITION BY item_statistics.item_id 
              ORDER BY item_statistics.score DESC
            )').as('row_num')
)

query = Arel::Nodes::As.new(sub_query, Arel.sql(filter.name))

join_clause = Arel::Nodes::InnerJoin.new(
    query,
    Arel::Nodes::On.new(
      Book.arel_table[:id].eq(filter[:book_id])
        .and(filter[:row_num].lteq(3))
    )
  )

Book
 .select(Book.arel_table[Arel.star],filter[:item_id])
 .joins(join_clause)
 .group_by(&:item_id)

这应该会产生以下 SQL:

SELECT 
    books.*,
    filtered_results.item_id
FROM 
    books 
    INNER JOIN (
      SELECT 
        item_statistics.*,
        ROW_NUMBER() OVER(
          PARTITION BY item_statistics.item_id 
          ORDER BY item_statistics.score DESC
        ) as row_number
      FROM 
        item_statistics
    ) AS filtered_results ON books.id = filtered_results.book_id 
            AND filtered_results.row_number <= 3

然后我们按item_id(虚拟属性)对所有书籍进行分组,所以结果是

1 => [Book,Book,Book], 2 => [Book,Book,Book]

Array 的结果大小应为

【讨论】:

以上是关于按列分组,结果限制并按另一列轨道排序的主要内容,如果未能解决你的问题,请参考以下文章

Python:如何按一列分组行并按另一列选择一行?

计算 20 秒间隔内的平均值并按另一列分组

将一列的多个结果行连接成一个,按另一列分组[重复]

按另一列值分组和计数

pandas/matplotlib 中一列按另一列分组的箱形图

熊猫数据框:按列子集+按另一列分组