Ruby ActiveRecord 组和“AS”处或附近的平均“语法错误”
Posted
技术标签:
【中文标题】Ruby ActiveRecord 组和“AS”处或附近的平均“语法错误”【英文标题】:Ruby ActiveRecord group and average "syntax error at or near "AS"" 【发布时间】:2017-03-16 07:05:28 【问题描述】:params = device_id: "u100", device_point: "1", point_no: "1", max_date: "2016-12-01 12:00", min_date: "2016-12-01 11:40"
我正在使用 PG 数据库的 ruby/rails 环境中工作。
我正在尝试添加到我的设备控制器以使用 ActiveRecord 从一些虚拟传感器数据中获取 10 分钟的平均值。 我可以按分钟分组;
.group("date_trunc('minute', device_time)").average('point_data_val')
例如
device_data = DeviceDatum.select('device_time, point_data_val').filter(params.slice(:device_id, :device_point, :point_no, :iot_version, :iot_time, :device_time, :point_data_type, :point_data_val, :point_bat_val,:min_val, :max_val, :min_date, :max_date)).limit(1008).group("date_trunc('minute', device_time)").average('point_data_val')
(240.3ms) SELECT AVG("device_data"."point_data_val") AS average_point_data_val, date_trunc('minute', device_time) AS date_trunc_minute_device_time FROM "device_data" WHERE "device_data"."device_id" = $1 AND "device_data"."device_point" = $2 AND "device_data"."point_no" = $3 AND (device_time >= '2016-12-01 11:40') AND (device_time <= '2016-12-01 12:00') GROUP BY date_trunc('minute', device_time) LIMIT 1008 [["device_id", "u100"], ["device_point", 1], ["point_no", 1]]
=> 2016-12-01 11:41:00 +0900=>#<BigDecimal:7f91599cfbc0,'-0.4816E1',18(27)>, 2016-12-01 11:51:00 +0900=>#<BigDecimal:7f91599cf8f0,'-0.4868E1',18(27)>
我找到了this method 来做这件事 但是当我尝试在组方法中使用 AS 时
DeviceDatum.select('device_time, point_data_val')
.filter(params.slice(:device_id, :device_point, :point_no, :iot_version, :iot_time, :device_time,
:point_data_type, :point_data_val, :point_bat_val,:min_val, :max_val, :min_date,
:max_date)).limit(1008)
.group("date_trunc('hour', device_time) AS hour_stump,
(extract(minute FROM device_time)::int / 10)
AS min10_slot,count(*)").average('point_data_val')
我收到此错误。
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near "AS"
LINE 1: ... 12:00') GROUP BY date_trunc('hour', device_time) AS hour_st... : SELECT AVG("device_data"."point_data_val") AS average_point_data_val, date_trunc('hour', device_time) AS hour_stump,(extract(minute FROM device_time)::int / 10) AS min10_slot,count(*) AS date_trunc_hour_device_time_as_hour_stump_extract_minute_from_d FROM "device_data" WHERE "device_data"."device_id" = $1 AND "device_data"."device_point" = $2 AND "device_data"."point_no" = $3 AND (device_time >= '2016-12-01 11:40') AND (device_time <= '2016-12-01 12:00') GROUP BY date_trunc('hour', device_time) AS hour_stump,(extract(minute FROM device_time)::int / 10) AS min10_slot,count(*) LIMIT 1008
from ...../bundle/ruby/2.1.0/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:637:in `prepare'
ActiveRecord 似乎也在使用它为平均值生成的 sql 中的 group 方法中的选项。
SELECT
AVG("device_data"."point_data_val") AS average_point_data_val,
date_trunc('hour', device_time) AS hour_stump,
(
extract(minute
FROM
device_time)::int / 10
)
AS min10_slot,
count(*) AS date_trunc_hour_device_time_as_hour_stump_extract_minute_from_d
FROM
"device_data"
WHERE
"device_data"."device_id" = $1
AND "device_data"."device_point" = $2
AND "device_data"."point_no" = $3
AND
(
device_time >= '2016-12-01 11:40'
)
AND
(
device_time <= '2016-12-01 12:00'
)
GROUP BY
date_trunc('hour', device_time) AS hour_stump,
(
extract(minute
FROM
device_time)::int / 10
)
AS min10_slot,
count(*) LIMIT 1008
我在这里错过了什么?
【问题讨论】:
如果我没记错的话你只能在SELECT
中使用AS
您在group by
子句中尝试做的事情是否可行?您所指的问题在 select 子句中使用了这个技巧。
【参考方案1】:
我认为你的group
子句应该是这样的:
group("hour_stump, min10_slot,
date_trunc_hour_device_time_as_hour_stump_extract_minute_from_d")
如果您在select
子句中使用别名。正如@Fallenhero 和@Iceman 所说,group by
中的别名是不允许的。
如果在select
中自动替换别名,我认为唯一的方法是按原样使用函数
group("date_trunc('hour', device_time),
(extract(minute FROM device_time)::int / 10), count(*)")
.
【讨论】:
谢谢,我选择了:group("to_char(date_trunc('hour', device_time), 'YYYY-MM-DD HH:') || to_char((extract(minutes FROM device_time)::int / 10*10), 'fm00')")
,这给了:[["2016-12-01 11:00", #<BigDecimal:7f883988e348,'-0.3998E1',18(27)>], ["2016-12-01 11:10", #<BigDecimal:7f883988e500,'-0.4274E1',18(27)>], ["2016-12-01 11:20", #<BigDecimal:7f883988e438,'-0.453E1',18(27)>], ["2016-12-01 11:30", #<BigDecimal:7f883988e758,'-0.4605E1',18(27)>], ["2016-12-01 11:40", #<BigDecimal:7f883988e690,'-0.4816E1',18(27)>], ["2016-12-01 11:50", #<BigDecimal:7f883988e5c8,'-0.4868E1',18(27)>]]
已更新为group("to_timestamp(to_char(date_trunc('hour', device_time), 'YYYY-MM-DD HH:') || (to_char((extract(minutes FROM device_time)::int / 10*10), 'fm00')), 'YYYY-MM-DD HH:MI')::timestamp without time zone").calculate(params[:func], 'point_data_val')
这会将输出格式化为漂亮的时间戳,并且'::time stamp without time zone' 将时间缩短了九个小时以上是关于Ruby ActiveRecord 组和“AS”处或附近的平均“语法错误”的主要内容,如果未能解决你的问题,请参考以下文章