【发布时间】:2018-01-20 00:12:57
【问题描述】:
我正在尝试在 sql 查询之后用 Ecto 语法编写,如何在 FROM hierarchy, 行之后编写子查询,它在 from 子句中,但我怀疑在 Ecto 中是否可行?我想知道我是否可以使用表连接甚至横向连接来执行这样的查询,而不会造成性能损失并获得相同的效果?
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)
我坚持使用以下代码:
hierarchy_subquery =
Hierarchy
|> distinct([h], h.parent)
Route
|> select([r], r.id, r.name)
|> where([r], r.id in subquery(hierarchy_subquery))
架构:
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
编辑我测试了各种查询的性能,下面这个是最快的:
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
与上述相同的查询,但 join 替换为 inner_lateral_join 用于分段子查询:
计划时间:~1.353 ms 执行时间:~38.518 ms
来自答案的子查询:
计划时间:~1.017 ms 执行时间:~41.288 ms
我认为inner_lateral_join 会更快,但事实并非如此。有谁知道如何加快这个查询?
【问题讨论】:
-
您是否有一个更简单的查询作为起点?例如,我找不到
osm的来源。 -
我已经更正了我的sql查询,实际上我知道如何用
ST_Intersects写fragment,但不知道子查询。
标签: postgresql elixir phoenix-framework ecto