【问题标题】:How calculate things from many tables by using a few queries?如何通过使用一些查询从许多表中计算事物?
【发布时间】:2012-02-09 13:04:18
【问题描述】:

注意:这个问题与PostGIS和Postgresql有关,是用PHP实现的

现在我有表 A:

gid | kstart  | kend    | ctrl_sec_no | the_geom | 
626 | 238     | 239     | 120802      | 123456   |
638 | 249     | 250     | 120802      | 234567   |
4037| 239     | 249     | 120802      | 345678   |

注意:the_geom 是一个几何值(类型:LINE),在这种情况下,为了便于阅读,我将它们随机化

和表 B:

gid | ctrl_sec_no | x   | the_geom
543 | 120802      | 239 | null
544 | 120802      | 247 | null

[PostGIS 描述] 这两张表是通过ctrl_sec_no联系起来的,也就是说表A的ctrl_sec_no 120802上的3个连续的LINE,连成一条LINE,包含表B的两个POINT。我们只知道距离{MAX(kend) - MIN(kstart)} LINE 和它在 LINE 上的公里 (x)。

问题是 PostgreSQL 的查询是什么。

(a.) 选择 A.kend 中的最大值,减去 A.kstart 中的最小值 -> 250 - 238 = 12

(b.) 从 A.kend 中选择最大值,减去 B 中的 'x' 值 -> 250 - 239 = 11

(c.) 从这两个值计算比率 ((b.)/(a.)) -> 11/12

(d.) 使用 PostGIS:ST_Interpolate -> ST_Interpolate(A.the_geom, 11/12) 注意:这个函数是用来和LINE一起找到POINT的,另一方面是定义POINT所在的位置

(e.) 我们将从 (d.) 中获取一个值,并使用它来更新表 B 的“the_geom”列,该列最初为 NULL。

(f.) 为表 B 中的每一行循环这组查询。

[PostGIS 描述] 这组查询的目的是通过计算一些数学来确定表 B 中的 the_geom,并将输出放入 ST_Interpolate 函数以获得表 B 中 POINT 所在位置的 the_geom。

感谢高级版,我知道这是一个非常复杂的问题。我不介意您是否会使用太多查询。只是为了得到正确的值。

这些是在 danihp 帮助下的实际查询(最终)。

with CTE( max_kend) as (
 SELECT MAX(A.kend)
 FROM centerline A
),
r_b as (
 select B.ctrl_sec_no,B.gid, MAX(CTE.max_kend) - B.km as b
  FROM land_inventory B cross join CTE group by B.gid,B.ctrl_sec_no,B.km
),
r_a as (
    SELECT MAX(A.kend) - MIN(A.kstart) as a
    FROM centerline A
),
r_ratio as (
  select r_b.gid, r_b.b / r_a.a  as my_ratio
  from r_a cross join r_b
),
r_new_int as (
select B.gid,r_ratio.my_ratio,B.ctrl_sec_no,B.km,ST_AsText(ST_Envelope(ST_Collect(ST_line_interpolate_point(A.the_geom,  r_ratio.my_ratio )))) as new_int from centerline A, land_inventory B inner join r_ratio on B.gid = r_ratio.gid where A.ctrl_sec_no = B.ctrl_sec_no group by B.ctrl_sec_no,B.gid,r_ratio.my_ratio,B.km order by B.ctrl_sec_no
) 
UPDATE land_inventory
set land_inventory.the_geom = n.new_int
from r_new_int n
where 
  n.gid = land_inventory.gid and
  land_inventory.the_geom is NULL;

【问题讨论】:

  • 我已经尝试了所有这些,方法是在 PHP 上执行所有使用太多查询的步骤。 // 例如,“select max(kend) from A”然后“select min(kstart) from A”并做减法。然后将其保存在变量中并开始查询下一步。
  • 250 (Max kstart from Table A) - 239 (x on Table B, first row) = 11 之后我们将逐行循环步骤。
  • 逐行迭代不是强制性的。查看最终查询。

标签: php sql postgresql postgis


【解决方案1】:

好的,我们走吧。

(a)

SELECT MAX(A.kend) - MIN( A.kstart) as a
FROM Table A

(b)

已编辑假设 gid 是表 B 的 PK ...

with CTE( max_kend, min_x) as (
 SELECT MAX(A.kend), NULL
 FROM TableA A
)
select B.gid, MAX(CTE.max_kend) - B.min_x as b
 FROM TableB B 
 cross join CTE

(c)

with CTE( max_kend, min_x) as (
 SELECT MAX(A.kend), NULL
 FROM TableA A
),
r_b as (
 select B.gid, MAX(CTE.max_kend) - B.min_x as b
  FROM TableB B 
  cross join CTE
),
r_a as (
    SELECT MAX(A.kend) - MIN( A.kstart) as a
    FROM Table A
)
select r_b.gid, r_a.a / r_b.b as my_ratio
from r_a cross join r_b

(d)

with CTE( max_kend, min_x) as (
 SELECT MAX(A.kend), NULL
 FROM TableA A
),
r_b as (
 select B.gid, MAX(CTE.max_kend) - B.min_x as b
  FROM TableB B 
  cross join CTE
),
r_a as (
    SELECT MAX(A.kend) - MIN( A.kstart) as a
    FROM Table A
),
r_ratio as (
  select r_b.gid, r_a.a / r_b.b as my_ratio
  from r_a cross join r_b
)
select ST_Interpolate(A.the_geom,  r_ratio.my_ratio )   
from TableB B 
inner join r_ratio on B.gid = r_ratio.gid

(e, f)

with CTE( max_kend, min_x) as (
 SELECT MAX(A.kend), NULL
 FROM TableA A
),
r_b as (
 select B.gid, MAX(CTE.max_kend) - B.min_x as b
  FROM TableB B 
  cross join CTE
),
r_a as (
    SELECT MAX(A.kend) - MIN( A.kstart) as a
    FROM Table A
),
r_ratio as (
  select r_b.gid, r_a.a / r_b.b as my_ratio
  from r_a cross join r_b
),
r_new_int as (
  select ST_Interpolate(A.the_geom,  r_ratio.my_ratio ) as new_int
  from TableB B 
  inner join r_ratio on B.gid = r_ratio.gid
)
UPDATE tableB
set tableB.the_geom = n.new_int
from r_new_int n
where 
  n.gid = tableB.gid and
  tableB.the_geom  is NULL

免责声明,不是 testet。

已编辑

with CTE( max_kend) as (
 SELECT MAX(A.kend)
 FROM centerline A
),
r_b as (
 select B.ctrl_sec_no,B.gid, MAX(CTE.max_kend) - B.km as b
  FROM land_inventory B cross join CTE group by B.gid,B.ctrl_sec_no,B.km
),
r_a as (
    SELECT MAX(A.kend) - MIN(A.kstart) as a
    FROM centerline A
),
r_ratio as (
  select r_b.gid, r_b.b / r_a.a  as my_ratio
  from r_a cross join r_b
),
r_new_int as (
  select     
    B.gid,
    r_ratio.my_ratio,
    B.ctrl_sec_no,B.km,
    ST_AsText(ST_Envelope(ST_Collect(
          ST_line_interpolate_point(A.the_geom,  r_ratio.my_ratio 
    )))) as new_int 
  from 
    centerline A inner join
    land_inventory B 
       on A.ctrl_sec_no = B.ctrl_sec_no 
       inner join 
    r_ratio on B.gid = r_ratio.gid 
  group by B.ctrl_sec_no,B.gid,r_ratio.my_ratio,B.km order by B.ctrl_sec_no
) 
UPDATE land_inventory
set the_geom = n.new_int
from r_new_int n
where 
  n.gid = land_inventory.gid and
  land_inventory.the_geom is NULL;

【讨论】:

  • 我正在测试和优化查询,这对您的帮助很有趣:) 请等我。
  • 只是告诉你这组查询是正确的(现在我正在处理插值)
  • 好的,我们开始吧,我刚刚添加了从您的第一个查询 danihp 中提炼出来的实际查询。但是你在计算比率时有一些小错误,我已经纠正了。第二个错误来自我>
  • 好的,下一个问题(纯粹是关于 PostGIS)在 stackoverflow.com/questions/9213026/…
  • 稍等片刻,我正在将其细化为实际查询。
猜你喜欢
  • 2020-12-09
  • 2018-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多