rails清理

pvcm50d1  于 2021-09-29  发布在  Java
关注(0)|答案(1)|浏览(572)

我试图用子查询清理sql查询,但每次都会出现语法错误或无效几何体错误。对于清理,我使用清理sql数组函数。
SQL查询

  1. SELECT ST_Distance('SRID=4326;POINT(0 0)'::geometry, subqry.centroid)
  2. FROM
  3. (SELECT ST_AsText(ST_Centroid('SRID=4326;MULTIPOINT ( 0 0, 0 0, 0 0, 0 0 )'))::geography as centroid
  4. ) as subqry;

第一种方法

  1. ActiveRecord::Base::sanitize_sql_array(["select ST_Distance('SRID=4326;POINT(? ?)'::geometry, :sub_query", sub_query: "(SELECT ST_Centroid(SRID=4326;'MULTIPOINT ( ? ?, ? ?, ? ?, ? ? )'::geometry) as centroid) as sub_query", min_longitude, min_latitude, min_longitude, min_latitude, min_longitude, max_latitude, max_longitude, min_latitude, max_longitude, max_latitude])

第二种方法
这里我得到“srid=4326;se“<--几何体中位置13处的分析错误

  1. ActiveRecord::Base::sanitize_sql_array(["ST_Distance('SRID=4326;POINT(? ?)'::geometry, 'SRID=4326; SELECT ST_AsText(ST_Centroid(MULTIPOINT ( ? ?, ? ?, ? ?, ? ? ))) as centroid'::geometry)", min_longitude, min_latitude, min_longitude, min_latitude, min_longitude, max_latitude, max_longitude, min_latitude, max_longitude, max_latitude])

postgis中的st_质心&st_距离法示例

  1. st_centroid
  2. SELECT ST_AsText(ST_Centroid('MULTIPOINT ( -1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6 )'));
  3. st_distance
  4. SELECT ST_Distance(
  5. 'SRID=4326;POINT(-72.1235 42.3521)'::geometry,
  6. 'SRID=4326;LINESTRING(-72.1260 42.45, -72.123 42.1546)'::geometry
  7. );
but5z9lq

but5z9lq1#

你可以通过一些小技巧和大量arel(这将为你处理卫生问题)构建任何你想要的查询。
警告:这可能看起来不漂亮,但它可以非常灵活,并应产生预期的结果(这只会产生所需的查询,如帖子所示(我不知道所需的语法是否正确,因为我从未使用过postgis)

  1. class PostGISQuery
  2. def initialize(srid,points,point)
  3. @srid = srid
  4. @points = points
  5. @point = point
  6. end
  7. def build_query
  8. return @query if @query
  9. multi_point = Arel::Nodes::NamedFunction.new("MULTIPOINT",[lat_long(@points)])
  10. centroid = Arel::Nodes::NamedFunction.new('ST_AsText',[
  11. Arel::Nodes::NamedFunction.new('ST_Centroid',[
  12. Arel.sql("SRID=#{@srid};#{multi_point.to_sql}")
  13. ])
  14. ])
  15. mgr = Arel::SelectManager.new
  16. mgr.project(cast_geometry(centroid).as('centroid'))
  17. table = Arel::Table.new('subqry')
  18. answer= Arel::Nodes::NamedFunction.new('ST_Distance',[
  19. cast_geometry(Arel.sql("SRID=#{@srid};#{Arel::Nodes::NamedFunction.new('POINT',lat_long([@point])).to_sql}")),
  20. table[:centroid]
  21. ])
  22. mgr2 = Arel::SelectManager.new(Arel::Nodes::As.new(mgr,Arel.sql(table.name)))
  23. @query = mgr2.project(answer.as('answer'))
  24. end
  25. def execute
  26. ActiveRecord::Base.connection.exec_query(build_query.to_sql)
  27. end
  28. private
  29. def cast_geometry(arel)
  30. Arel::Nodes::NamedFunction.new("CAST",[arel.as('geometry')])
  31. end
  32. def lat_long(arr)
  33. arr.map {|a| Arel.sql(a.join(' '))}
  34. end
  35. end

使用

  1. srid = 4326
  2. points = [[1, 0], [-1, 2], [-1, 3], [-1, 4], [-1, 7], [0, 1], [0, 3], [1, 1], [2, 0], [6, 0], [7, 8], [9, 8], [10, 6]]
  3. point = [-72.1235, 42.3521]
  4. qry = PostGISQuery.new(srid,points,point)
  5. qry.execute
  6. # => ActiveRecord::Result

sql生成:

  1. SELECT
  2. ST_Distance(
  3. CAST('SRID=4326;POINT(-72.1235 42.3521)' AS geometry),
  4. "subqry"."centroid") AS answer
  5. FROM (
  6. SELECT
  7. CAST(ST_AsText(
  8. ST_Centroid(
  9. 'SRID=4326;MULTIPOINT(1 0, -1 2, -1 3, -1 4, -1 7, 0 1, 0 3, 1 1, 2 0, 6 0, 7 8, 9 8, 10 6)'
  10. )
  11. ) AS geometry) AS centroid
  12. ) AS subqry
展开查看全部

相关问题