首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在ecto中编写复杂的子查询作为from子句?

如何在ecto中编写复杂的子查询作为from子句?
EN

Stack Overflow用户
提问于 2018-01-20 00:12:57
回答 1查看 1.4K关注 0票数 1

我试图在subquery之后用Ecto语法编写,如何在FROM hierarchy,行之后编写子查询,它在from子句中,但我怀疑Ecto中是否可行?我想知道是否可以使用表联接甚至横向联接来执行这样的查询,而不会造成同样的性能损失?

代码语言:javascript
运行
复制
SELECT routes.id, routes.name
FROM routes
WHERE routes.id IN
  (SELECT DISTINCT hierarchy.parent
   FROM hierarchy,
    (SELECT DISTINCT unnest(segments.rels) AS rel
     FROM segments
     WHERE ST_Intersects(segments.geom, ST_SetSrid(ST_MakeBox2D(ST_GeomFromText('POINT(1866349.262143 6886808.978425)', -1), ST_GeomFromText('POINT(1883318.282423 6876413.542579)', -1)), 3857))) AS anon_1
   WHERE hierarchy.child = anon_1.rel)

我坚持了以下代码:

代码语言:javascript
运行
复制
hierarchy_subquery =
  Hierarchy
  |> distinct([h], h.parent)
Route
|> select([r], r.id, r.name)
|> where([r], r.id in subquery(hierarchy_subquery))

模式:

代码语言:javascript
运行
复制
defmodule MyApp.Hierarchy do
  use MyApp.Schema

  schema "hierarchy" do
    field :parent, :integer
    field :child, :integer
    field :deph, :integer
  end
end
defmodule MyApp.Route do
  use MyApp.Schema

  schema "routes" do
    field :name, :string
    field :intnames, :map
    field :symbol, :string
    field :country, :string
    field :network, :string
    field :level, :integer
    field :top, :boolean
    field :geom, Geo.Geometry, srid: 3857
  end
end
defmodule MyApp.Segment do
  use MyApp.Schema

  schema "segments" do
    field :ways, {:array, :integer}
    field :nodes, {:array, :integer}
    field :rels, {:array, :integer}
    field :geom, Geo.LineString, srid: 3857
  end
end

我已经测试过各种查询的性能,下面的编辑是最快的:

代码语言:javascript
运行
复制
from r in Route,
        join: h in Hierarchy, on: r.id == h.parent,
        join: s in subquery(
          from s in Segment,
            distinct: true,
            where: fragment("ST_Intersects(?, ST_SetSrid(ST_MakeBox2D(ST_GeomFromText('POINT(1285982.015631 7217169.814674)', -1), ST_GeomFromText('POINT(2371999.313507 6454022.524275)', -1)), 3857))", s.geom),
            select: %{rel: fragment("unnest(?)", s.rels)}
        ),
        where: s.rel == h.child,
        select: {r.id, r.name}

结果:

计划时间:~0.605 ms执行时间:~37.232 ms

与上面的查询相同,但对于段子查询,joininner_lateral_join替换为:

计划时间:~1.353 ms执行时间:~38.518 ms

答复中的子查询:

计划时间:~1.017 ms执行时间:~41.288 ms

我以为inner_lateral_join会更快,但它不是。有人知道如何加速这个查询吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-20 11:40:02

以下是我要尝试的。我还没有证实它是否有效,但它应该指向正确的方向:

代码语言:javascript
运行
复制
segments =
  from s in Segment,
    where: fragment("ST_Intersects(?, ST_SetSrid(ST_MakeBox2D(ST_GeomFromText('POINT(1866349.262143 6886808.978425)', -1), ST_GeomFromText('POINT(1883318.282423 6876413.542579)', -1)), 3857)))", s.geom),
    distinct: true,
    select: %{rel: fragment("unnest(?)", s.rel)}

hierarchy =
  from h in Hierarchy,
    join: s in subquery(segments),
    where: h.child == s.rel,
    distinct: true,
    select: %{parent: h.parent}

routes =
  from r in Route,
    join: h in subquery(hierarchy),
    where: r.top and r.id == h.parent

要记住的事情:

  1. 从内部查询开始,然后转到外部查询
  2. 要访问子查询的结果,需要在子查询中选择一个映射。
  3. Ecto只允许子查询在from和join中。好消息是,您通常可以将"x IN subquery“重写为联接。
  4. 您可以尝试单独运行每个查询,并查看它们是否有效。
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48351295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档