【问题标题】:Rails combine group by and minRails 结合了 group by 和 min
【发布时间】:2020-02-04 04:02:44
【问题描述】:

假设我们有一个名为Activities的表

+-----------+-----------+------------+--------------+
| player_id | device_id | event_date | games_played |
+-----------+-----------+------------+--------------+
| 1         | 2         | 2016-03-01 | 5            |
| 1         | 2         | 2016-05-02 | 6            |
| 2         | 3         | 2017-06-25 | 1            |
| 3         | 1         | 2016-03-02 | 0            |
| 3         | 4         | 2018-07-03 | 5            |
+-----------+-----------+------------+--------------+

我想找出 player_id 并且它是 first event_date 作为 first_date。

SQL:

SELECT Activities.player_id, min(Activities.event_date) as first_date 
FROM `activities` 
GROUP BY `activities`.`player_id`

结果表:

+-----------+-------------+
| player_id | first_login |
+-----------+-------------+
| 1         | 2016-03-01  |
| 2         | 2017-06-25  |
| 3         | 2016-03-02  |
+-----------+-------------+

如何在 Rails 中做到这一点?

我已经尝试过这个,但检索到一个仅包含 player_idActivity 集合。

Activity.select('Activities.player_id, min(Activities.event_date) as first_date')
        .group(:player_id)

这样

[#<Activity:0x00007f94923bb888 player_id: 1>, #<Activity:0x00007f94923bb608 player_id: 2>, #<Activity:0x00007f94923b9ba0 player_id: 3>]

【问题讨论】:

  • 当您在 select 语句中指定自定义名称时,rails 会自动将其创建为对象上的方法名称。例如activities = [#&lt;Activity:0x00007f94923bb888 player_id: 1&gt;]; activities.first.first_date
  • 试试to_json,你也能看到first_date
  • 你到底是怎么得到那个 SQL 输出的?您选择 SELECT Activities.player_id, min(Activities.event_date) as first_date 并在结果中得到 player_iddevice_id 完全没有意义。这不会发生。
  • @max,对不起,我输入了完全错误的列名。表格已更新

标签: sql ruby-on-rails activerecord


【解决方案1】:

其实你上面的查询结果

result = [#<Activity:0x00007f94923bb888 player_id: 1>, #<Activity:0x00007f94923bb608 player_id: 2>, #<Activity:0x00007f94923b9ba0 player_id: 3>]

加载 first_date 列,因为 first_date 不是 Activity 对象的属性,rails 不会以这种方式显示虚拟列。 您可以使用此语法访问它

result.last.first_date

如果您需要查看结果对象中的日期值,请像这样修改您的查询

Activity.select('Activities.player_id, min(Activities.event_date) as event_date').group(:player_id)

那么你就可以得到你想要的结果

<Activity:0x00007f94923bb608 player_id: 2, event_date: 'date value' >, #<Activity:0x00007f94923b9ba0 player_id: 3, event_date: 'date value' >]

【讨论】:

    【解决方案2】:

    在结果中您只得到了 player_id,因为当您执行 Activity.select('..') 时,rails 返回 ActiveRecord 模型对象。

    您可能想要运行自定义查询并将输出转换为这样的数组:

    result = ActiveRecord::Base.connection.execute("SELECT Activities.player_id, min(Activities.event_date) as first_date FROM activities GROUP BY activities.player_id")
    result.to_a # Converts PG::Result to an array, 'result.as_json' converts to json
    

    希望这会有所帮助。

    【讨论】:

    • 它确实有效。但也许我没有很好地解决我的问题,我想知道为什么first_date 没有出现在我的查询中。我已经从另一个人那里得到了答案。不过还是谢谢!
    • @CodaChang - 我在回答的第一句话中回答了这个问题。请检查上面,你会明白的。要添加更多内容,Activity 模型无法识别 first_date。
    • 感谢您解释详细信息。我现在明白了。
    猜你喜欢
    • 2013-04-06
    • 2012-07-25
    • 2012-07-25
    • 2013-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-26
    相关资源
    最近更新 更多