Ecto.QueryError 在子查询上

Ecto.QueryError on a subquery

对于以下查询:

sub_query = from sq in Database.Nestoria,
  distinct: sq.lister_url,
  select: [sq.place_name,
          sq.price,
          sq.price_type],
  where: fragment("cast(to_char(?, 'YYYYMMDD') AS INTEGER) >= (SELECT cast(to_char(max(inserted_at), 'YYYYMMDD') AS INTEGER) - 1 FROM nestoria)", sq.inserted_at),
  where: sq.bedroom_number == 1

query = from un in Database.Underground,
  left_join: ne in subquery(sub_query), on: un.station_name_slug == ne.place_name,
  select: [ un.lines_id,
            un.station_name,
            un.display_name,
            ne.place_name,
            fragment("count(?) as data_count", ne.place_name),
            fragment("Avg(CASE WHEN ? = 'weekly' THEN price * ( 31 / 7 ) ELSE price END) AS avg_monthly_price ", ne.price_type)],
  group_by: [un.lines_id,
            un.station_name,
            un.display_name,
            ne.place_name],
  order_by: [ne.place_name]

output = Repo.all(query)

我收到以下错误:

** (Ecto.QueryError) subquery must select a source (t), a field (t.field) or a map, got: [&0.place_name(), &0.price(), &0.price_type()]

奇怪的是我在一个非常相似的项目中毫无困难地拥有了这个 运行。所有模式都正常工作,没有任何问题(Repo.all(Nestoria/Underground)returns 很好)。

从 Ecto 的当前版本开始,子查询不能有一个 select 以列表作为值。即使这以某种方式起作用,您也无法在问题的查询中执行 ne.place_name,因为 ne 将是列表,而不是地图。

您可以 select 手动创建地图:

select: %{place_name: sq.place_name, price: sq.price, ...}

或使用mapstruct:

select: map(sq, [:place_name, :price, :price_type])
# or
select: struct(sq, [:place_name, :price, :price_type])

或者只传递一个字段列表,相当于上面的struct版本:

select: [:place_name, :price, :price_type]