我正在尝试在此查询中使用 generate_series 来获取某个时间段内的销售数量,即使没有销售的日子也是如此。我以硬编码的价格使用它,但自合同创建以来,现在我需要获得所有销售额。
到目前为止我所拥有的:
query =
from(
c in Contract,
join: v in Voucher,
on: v.contract_id == c.id,
join: s in Sale,
on: s.voucher_id == v.id and c.id == ^contract_id,
right_join:
day in fragment(
"select generate_series(current_date - interval '60 day', current_date, '1 day')::date AS d"
),
on: day.d == fragment("date(?)", s.date),
group_by: day.d,
select: %{
number_sales: count(s.id),
total_value: sum(s.value),
date: day.d
},
order_by: [asc: day.d]
)
Repo.all(query)
|> Enum.map(fn entry -> Map.put(entry, :date, Date.from_erl!(entry.date)) end)
通过该查询,即使没有销售的日子,我也能获得过去60天的所有销售。
我现在将generate_series('2018-06-01', current_date, '1 day')
行更改为
从合同创建之日开始,但出现以下错误:
[debug] QUERY ERROR source="contracts" db=1.0ms
SELECT count(s2."id"), sum(s2."value"), f3."d" FROM "contracts" AS c0 INNER
JOIN "vouchers" AS v1 ON v1."contract_id" = v1."id" INNER JOIN "sales" AS s2
ON (s2."voucher_id" = v1."id") AND (c0."id" = $1) RIGHT OUTER JOIN (select
generate_series(c0."inserted_at", current_date, '1 day')::date AS d) AS f3 ON
f3."d" = date(s2."date") GROUP BY f3."d" ORDER BY f3."d" [1]
** (Postgrex.Error) ERROR 42P01 (undefined_table): invalid reference to FROM-
clause entry for table "c0"
(ecto) lib/ecto/adapters/sql.ex:431: Ecto.Adapters.SQL.execute_and_cache/7
(ecto) lib/ecto/repo/queryable.ex:133: Ecto.Repo.Queryable.execute/5
(ecto) lib/ecto/repo/queryable.ex:37: Ecto.Repo.Queryable.all/4
(app) lib/app/contracts/contracts.ex:313: App.Contracts.get_sales_day/1
修改后的代码:
query =
from(
c in Contract,
join: v in Voucher,
on: v.contract_id == c.id,
join: s in Sale,
on: s.voucher_id == v.id and c.id == ^contract_id,
right_join:
day in fragment(
"select generate_series(?, current_date, '1 day')::date AS d",
c.inserted_at
),
on: day.d == fragment("date(?)", s.date),
group_by: day.d,
select: %{
number_sales: count(s.id),
total_value: sum(s.value),
date: day.d
},
order_by: [asc: day.d]
)
Repo.all(query)
|> Enum.map(fn entry -> Map.put(entry, :date, Date.from_erl!(entry.date)) end)
答案 0 :(得分:1)
这应该有效。
static final Function<Function<Double,Double>,Function<Double,Function<Double, Double>>>
integral = f -> a -> b ->
{
final double dx=(b-a)/100000;
return IntStream.range(0, 100000).mapToDouble(i -> f.apply(a+i*dx)*dx).sum();
};
如果您需要更大的灵活性,例如使用public static void main(String args[])
{
double result = integral.apply(x->x*x-x+3).apply(-5.0).apply(12.0);
System.out.println("Result is " + result);
}
,则可以将fragment("SELECT generate_series(?, current_date, '1 day')",
type(c.inserted_at, :naive_datetime)
)
更改为timestamptz
,将:datetime
更改为:string
并发送值作为字符串。示例:
?
时间间隔也一样:
?::timestamptz
答案 1 :(得分:0)
根据上面的答案,这是针对日期时间值的“分组”查询的通用解决方案(对于“分组”,datetime值比较困难,因为它们不落在与generate_series匹配的离散点上)。 即使没有事件数据,此解决方案也会生成序列点。如果缺少事件数据,请使用coalesce()函数将nil转换为0。 我正在使用一个名为Event的表,其中的字段为'dt'(日期时间),字段为'value'(整数)。
startpoint = startpoint = Timex.parse!("2011-04-18 12:00:00.000000Z", "{ISO:Extended}"
group_span = 20 # group_by interval in minutes
duration = 60 # in minutes, 24* 60 = 1 day, etc
query = from(e in Event,
right_join: minute in fragment(
"select
? + ( n || ' minutes')::interval start_time,
? + ( n+? || ' minutes')::interval end_time
from generate_series(0, ?, ?) n", type(^startpoint, :naive_datetime), type(^startpoint, :naive_datetime), ^group_span, ^duration, ^group_span),
on: e.dt >= minute.start_time and e.dt < minute.end_time,
group_by: minute.start_time,
order_by: [asc: minute.start_time],
select: [minute.start_time, avg(e.value) ]
)
结果
[
[~N[2011-04-18 12:00:00.000000], 3.0],
[~N[2011-04-18 12:20:00.000000], 0.0],
[~N[2011-04-18 12:40:00.000000], 0.0],
[~N[2011-04-18 13:00:00.000000], 0.0]
]