我试图避免在我的Rails应用程序中使用直接SQL,但需要做一个相当大的版本:
SELECT ds.product_id,
( SELECT SUM(units) FROM daily_sales WHERE (date BETWEEN '2015-01-01' AND '2015-01-08') AND service_type = 1 ) as wk1,
( SELECT SUM(units) FROM daily_sales WHERE (date BETWEEN '2015-01-09' AND '2015-01-16') AND service_type = 1 ) as wk2
FROM daily_sales as ds group by ds.product_id
我确信它可以做到,但我很难把它写成一个积极的记录声明。有人可以帮忙吗?
答案 0 :(得分:1)
如果必须在单个查询中执行此操作,则需要为CASE语句编写一些SQL。您需要以下内容:
ranges = [ # ordered array of all your date-ranges
Date.new(2015, 1, 1)..Date.new(2015, 1, 8),
Date.new(2015, 1, 9)..Date.new(2015, 1, 16)
]
overall_range = (ranges.first.min)..(ranges.last.max)
grouping_sub_str = \
ranges.map.with_index do |range, i|
"WHEN (date BETWEEN '#{range.min}' AND '#{range.max}') THEN 'week#{i}'"
end.join(' ')
grouping_condition = "CASE #{grouping_sub_str} END"
grouping_columns = ['product_id', grouping_condition]
DailySale.where(date: overall_range).group(grouping_columns).sum(:units)
这将生成带有数组键和数值的哈希。密钥的格式为[product_id, 'week1']
,其值将为该周的units
的相应总和。
答案 1 :(得分:0)
将您的SQL简化为以下内容并尝试转换它..
SELECT ds.product_id,
, SUM(CASE WHEN date BETWEEN '2015-01-01' AND '2015-01-08' AND service_type = 1
THEN units
END) WK1
, SUM(CASE WHEN date BETWEEN '2015-01-09' AND '2015-01-16' AND service_type = 1
THEN units
END) WK2
FROM daily_sales as ds
group by ds.product_id
答案 2 :(得分:0)
每个铁路开发人员迟早都会撞到Active Record query interface的墙壁,只是为了找到Arel中的解决方案。
Arel为您提供了创建查询所需的灵活性,而无需使用循环等。我不会给出可运行的代码,而是提示如何自己完成:
arel_table
来创建查询。对于名为Product
的模型,获取Arel表就像products = Product.arel_table
daily_sales.project(daily_sales[:units].count).where(daily_sales[:date].gt(BEGIN_DATE).where(daily_sales[:date].lt(END_DATE)
。您可以根据需要链接尽可能多的where
,并将其转换为SQL AND
。group
结合使用,您就完成了!