考虑以下问题:
SELECT DATE_TRUNC('hour', date_range)
FROM GENERATE_SERIES(:start_date, :end_date, :interval) as date_range
是否可以将GENERATE_SERIES(...)
用作表格(数据源)?理想情况下,它看起来像这样:
t = series(start, end, as: 'date_range')
dt = Arel::Nodes::NamedFunction.new('DATE_TRUNC', ['hour', t[:date_range]])
t.project(dt)
Upd1 即可。为什么我需要GENERATE_SERIES
?我有一些数据需要处理这个数据可用的时间戳,并将其输出为2D图。举一个简单的例子来考虑clickstream
=(id
,created_at
)。我想绘制一个特定日期之前针对给定日期时间网格(即Nov 17, Nov 18, Nov 19, ..., Nov 30
)的点击次数。事情是我希望这一切都发生在PostgreSQL中。
UPD2 即可。没有变量的示例查询可能如下所示:
SELECT DATE_TRUNC('hour', date_range) FROM GENERATE_SERIES('2015-01-01 00:15:38'::TIMESTAMP, '2015-01-10 23:59:59'::TIMESTAMP, '1 HOUR') as date_range;
答案 0 :(得分:5)
一种方法是简单地手动构建AST的所有必要部分
def timestamp(ts)
Arel::Nodes::NamedFunction.new(
'CAST', [
Arel::Nodes::As.new(
Arel::Nodes.build_quoted(ts),
Arel::Nodes::SqlLiteral.new('timestamp')
)
]
)
end
def series(from, to, by, options = {})
Arel::Nodes::NamedFunction.new(
'GENERATE_SERIES', [
timestamp(from),
timestamp(to),
Arel::Nodes::SqlLiteral.new(by)
]
).as(options.fetch(:as, 'series'))
end
def date_trunc(by, attribute)
Arel::Nodes::NamedFunction.new(
'DATE_TRUNC', [Arel.sql("'#{by}'"), attribute]
)
end
date_range = Arel::Table.new('date_range')
result = date_range.
from(series(5.days.ago, 4.days.ago, "'1 hour'", as: 'date_range')).
project(date_trunc('hour', date_range[:date_range]))
测试:
User.find_by_sql(result.to_sql).to_a.map &:attributes
SELECT DATE_TRUNC('hour', "date_range"."date_range")
FROM GENERATE_SERIES(
CAST('2015-02-03 21:29:22.729188' AS timestamp),
CAST('2015-02-04 21:29:22.729633' AS timestamp),
'1 hour'
) AS date_range
[{"date_trunc"=>2015-02-03 21:00:00 UTC, "id"=>nil},
{"date_trunc"=>2015-02-03 22:00:00 UTC, "id"=>nil},
{"date_trunc"=>2015-02-03 23:00:00 UTC, "id"=>nil},
{"date_trunc"=>2015-02-04 00:00:00 UTC, "id"=>nil},
# ...
{"date_trunc"=>2015-02-04 21:00:00 UTC, "id"=>nil}]