使用rails填充DATE_TRUNC分组的空白

时间:2016-12-31 21:42:53

标签: ruby-on-rails postgresql

对postgres数据库的以下查询

@interventos_2 = Intervento.where(['previsto >= ?', start_date]).group("DATE_TRUNC('week', previsto)").count

生成一个哈希,视图可以从中提取数据,如下所示

<% @interventos_2.each do |w| %>
  <%= w[0].strftime('%Y-%W') %> <%= w[1] %><br />
<% end %>

然而,如果在我们关注的周数范围内有空白(计数= 0),则年份和商业周的序列将看起来很奇怪或具有误导性。

声明范围然后用零填充空白周的有效方法是什么?

更新正在通过specific sql for performance reasons运行查询,因为数据集应该足够大,经常更改(缓存可能没有那么多帮助)并且经常被问到。

2 个答案:

答案 0 :(得分:1)

如果我理解正确,您希望提供全范围的YYYY-WW标签和计数,从start_date开始,无论某一周的数据是否存在。你没有提到previsto是Date,Time还是DateTime;我认为这只是一个时间,只是为了给您带来最大的不便。 =]

我认为您遇到的主要挑战是您将数据集与演示文稿混淆。我喜欢分别处理这两个:首先,获取数据并将其放入一周的格式;然后介绍范围。

为了获取数据,我更喜欢Railsy,更少数据库特定的解决方案。您的里程可能会有所不同,特别是如果您拥有大型数据集和/或需要使数据库完成繁重工作。这里的查询只获取每条记录的previsto字段,同时也强制数据库评估日期范围。可能是最简洁的查询而不必破坏SQL:

@interventos_2 = Intervento.select(:previsto).
  where(previsto: (start_date..Time.now)).
  map {|iv| iv.previsto.strftime('%Y-%W')}

请注意,这也会将结果映射到一个简单的YYYY-WW数组。说到这一点,让我们现在绘制YYYY-WW范围:

# make sure the end_date a clean multiple of 7 days from start_date
end_date = Date.today + (7 - (Date.today - start_date.to_date) % 7)
@timespan = (start_date.to_date..end_date).step(7).map {|date| date.strftime('%Y-%W')}

(可能有更多更整洁的方式来写)

鉴于这些比特,这里是您的观看代码的一个版本,它显示了整周的周数和该周的计数,即使它是0:

<% @timespan.each do |yearweek| %>
  <%= yearweek %> <%= @interventos_2.count(yearweek) %><br />
<% end %>

在bocca al lupo!

更新:您的更新说明您的用例需要直接SQL查询,因此请注意以下相同的一般方法:

@interventos_2 = Intervento.where(['previsto >= ?', start_date]).
  group("DATE_TRUNC('week', previsto)").count.
  map {|timestamp,count| [timestamp.strftime('%Y-%W'), count]}.to_h

# make sure the end_date a clean multiple of 7 days from start_date
end_date = Date.today + (7 - (Date.today - start_date.to_date) % 7)
@timespan = (start_date.to_date..end_date).step(7).map {|date| date.strftime('%Y-%W')}

<% @timespan.each do |yearweek| %>
  <%= yearweek %> <%= @interventos_2[yearweek] || 0 %><br />
<% end %>

答案 1 :(得分:0)

使用以下控制器方法,生成周数范围和视图所需的数据(beginning_of_week,除了数据本身外,还可以与有数据进行比较。)

@weeks = []
while start_date < final_date
   @weeks[start_date.year] = [] unless @weeks[start_date.year]
   @weeks << [start_date.beginning_of_week, start_date.cweek]
   start_date += 1.week
end
@weeks.reject!{|a| a.blank?}

因此,视图可以为每周生成布局项并将其与散列进行比较,并且在nil的位置生成零。

<% @weeks.each do |week| %>
    <% if !week.nil? %>
      <%= week[0] %>:  
      <% z = @interventos_2.detect {|f| f[0] == week[0] } %>
      <% if !z.nil? %>
        <%= z.to_a[1] %>
      <% else %>
        0
      <% end %>
  <% end %>