INNER将一个表与另外两个表连接起来,好像它们是外连接

时间:2016-06-07 19:22:28

标签: sql inner-join postgis

我在postgreSQL 9.5数据库中有三个表:

big_table:
 - geom_location
a:
 - geom_location
 - name
b:
 - geom_location
 - name

geom_location字段是已编制索引的postGIS字段。 a和b表的大小为200K行,而big_table大约为20M行 我需要创建一个产生以下结果的select语句:

  • a_name - 如果表a中geom_location的2Km内存在big_table条目,则这将是其关联名称。否则,它将为null。
  • b_name - 如果表b中geom_location的2Km内有big_table条目,则这将是其关联名称。否则,它将为null。
  • geom_location - 表a,b或两者中条目的2Km范围内的geom_location。
  • 我不想找回a_name和b_name都为空的任何行。

以下是我想要的,但它要求所有三个geom_locations都在2Km之内:

SELECT t.geom_location, a.name as a_name, b.name as b_name
FROM big_table t 
INNER JOIN a ON ST_DWithin(t.geom_location, a.geom_location, 2000) 
INNER JOIN b ON ST_DWithin(t.geom_location, b.geom_location, 2000)

这也非常接近,但它没有按照我想要的方式组合行:

SELECT t.geom_location, a.name as a_name, null as b_name
FROM big_table t 
INNER JOIN a ON ST_DWithin(t.geom_location, a.geom_location, 2000) 
UNION
SELECT t.geom_location, null as a_name, b.name as b_name
FROM big_table t 
INNER JOIN b ON ST_DWithin(t.geom_location, b.geom_location, 2000)

似乎应该有某种语法可以实现"主要是"内连接 - 也就是说,两个表相对于第一个表构成内部连接,但是相互之间是完全连接。

1 个答案:

答案 0 :(得分:0)

这样做你想要的吗?

SELECT t.geom_location, a.name as a_name, b.name as b_name
FROM big_table t LEFT JOIN
     a
     ON ST_DWithin(t.geom_location, a.geom_location, 2000) LEFT JOIN
     b
     ON ST_DWithin(t.geom_location, b.geom_location, 2000) AND a.name IS NULL
WHERE a.name IS NOT NULL OR b.name IS NOT NULL;

或者,您可以将ab合并在一起:

SELECT t.geom_location, ab.name, ab.which
FROM big_table t JOIN
     ((SELECT a.name a.geom_location, 'a' as which
       FROM a
      ) UNION ALL
      (SELECT a.name b.geom_location, 'b' as which
       FROM b
      )
     ) ab
     ON ST_DWithin(t.geom_location, ab.geom_location, 2000) ;

编辑:

我实际上认为上述解决方案可能会遇到一些性能问题。它适用于简单的数据类型,但复杂的类型总是有点麻烦。但是,你仍然可以做你想做的事。以下是union方法的变体:

with ta as(       SELECT t.geom_location,a.name as a_name,null as b_name       来自big_table t INNER JOIN            一个            ON ST_DWithin(t.geom_location,a.geom_location,2000      )     选择ta。*     来自ta     UNION ALL     SELECT t.geom_location,null为a_name,b.name为b_name     来自big_table t INNER JOIN          b          ON ST_DWithin(t.geom_location,b.geom_location,2000)     什么不存在(选择1                       来自ta                       在哪里t.geom_location = ta.geom_location                      );

我非常确定=应该在位置列上工作。

相关问题