按组分组 - Ruby / Rails + Postgres

5

我对ROR和Postgre都很陌生,现在想实现以下功能遇到了问题。

我有一个Working_hour模型和Merchant模型,其中商家(Merchant)有多个工作时间(working_hours),而每个工作时间(working_hour)都属于某一个商家(Merchant)。同一天内,商家可能会拥有两个或更多的工作时间。

我的视图:

 <% @merchant.working_hours.order(:day).group_by(&:day).each do |dia, whs| %>
   <%= t(:"date.abbr_day_names")[dia.to_i] %> : 
     <% whs.each do |wh| %>
       <li>
         <%= wh.oppening_hour.to_formatted_s(:time)  %> -
         <%= wh.close_hour.to_formatted_s(:time)  %>
       </li>
     <% end %>
  <% end %>

当我按照日期排序查看数据时,检索到的数据是这样的(请注意,开放时间是无序的):
Mon: 
17:00-20:00
10:00-13:00
Tue:
18:00-21:00 
10:00-13:00

我希望按照星期几进行分组,首先按照星期几排序,其次按照开放时间排序:
Mon: 
10:00-13:00
17:00-20:00
Tue:
10:00-13:00
18:00-21:00 

但是正如您所看到的,目前我正在使用Ruby层来完成这件事,这会带来性能问题。如何使用数据库层来实现这一点?


尝试搜索 - postgres按周分组 - 我曾经遇到过与mysql相同的问题,在阅读了一些文章后学到了更多的SQL知识,然后在Rails中就是自定义选择方法在类级别上... - Jakub Kuchar
你是否有任何default_scope影响了顺序? - Pavan
没有@Pavan。没有default_scope。 - user1301037
4个回答

2

为了在UI中按升序显示开放时间,工作时间应该按照opening_hour排序。一旦工作时间被排序,结果可以按天分组。

<% @merchant.working_hours.order(:opening_hour).group_by(&:day).each do |dia, whs| %> <%= t(:"date.abbr_day_names")[dia.to_i] %> : <% whs.each do |wh| %> <li> <%= wh.opening_hour.to_formatted_s(:time) %> - <%= wh.close_hour.to_formatted_s(:time) %> </li> <% end %> <% end %>


你应该解释这个答案是如何回答这个问题的。 - Smar

2
如果你愿意将数据存储在数据库表中(随机创建的数据集),这是一个快速的Postgres示例:
-- The query:
SELECT      to_char( mytime, 'day' ) as weekday,                -- example to get weekday name
            extract( dow from mytime ) as weekday_num,          -- example to get weekday number
            format(                                             -- format the way example output was given
                '%s - %s',
                date_trunc( 'hour', opening_time )::time(0),    -- get opening hour (without milliseconds)
                date_trunc( 'hour', closing_time )::time(0)     -- get closing hour (without milliseconds)
            ) as working_hours
FROM        mytable
GROUP BY    mytime,         -- to secure accurate ordering by timestamp
            weekday,        
            working_hours
ORDER BY    mytime,
            working_hours;

-- Result:
  weekday  | weekday_num |    working_hours
-----------+-------------+---------------------
 monday    |           1 | 08:00:00 - 17:00:00
 tuesday   |           2 | 08:00:00 - 16:00:00
 tuesday   |           2 | 08:00:00 - 17:00:00
 wednesday |           3 | 08:00:00 - 12:00:00
 thursday  |           4 | 08:00:00 - 12:00:00
 thursday  |           4 | 08:00:00 - 16:00:00
 friday    |           5 | 08:00:00 - 15:00:00
 friday    |           5 | 08:00:00 - 18:00:00

Postgres的文档链接可能会很方便:

https://www.postgresql.org/docs/current/static/functions-datetime.html https://www.postgresql.org/docs/current/static/functions-formatting.html https://www.postgresql.org/docs/current/static/functions-string.html#FUNCTIONS-STRING-FORMAT

附言:希望能提供一些在数据库中解决它的思路。

我该如何在Rails中调用这个?使用作用域(Scope)吗?您能否给我一个示例,如何将此查询抽象到Rails中? - user1301037
@user1301037 - 我不是Ruby的专家,但使用Activerecord来执行SQL是否有助于像这里给出的示例一样:https://dev59.com/8mUq5IYBdhLWcg3wEcNZ? - Kristo Mägi

2
<% day = nil %>
<% @merchant.working_hours.order(:day, :oppening_hour).each do |wh| %>
  <% if wh.day != day %>
    <% day = wh.day %>
    <%= t(:"date.abbr_day_names")[day.to_i] %> :
  <% end %>
  <li>
    <%= wh.oppening_hour.to_formatted_s(:time)  %> -
    <%= wh.close_hour.to_formatted_s(:time)  %>
  </li>
<% end %>

0

为什么你不能按照两个字段排序:按“日期”和“开放时间”?

<% @merchant.working_hours.order(:day).order(:oppening_hour).group_by(&:day).each do |dia, whs| %>
   <%= t(:"date.abbr_day_names")[dia.to_i] %> : 
     <% whs.each do |wh| %>
       <li>
         <%= wh.oppening_hour.to_formatted_s(:time)  %> -
         <%= wh.close_hour.to_formatted_s(:time)  %>
       </li>
     <% end %>
  <% end %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接