给定了经纬度的一张my_latlng表,和一个栅格my_grid表,怎么实现my_latlng表回填栅格id?

  • 场景:

假设我们拥有一个拥有了一系列经纬度的表my_latlng(lat string,lng string)表,还有一张给定的栅格表my_grid(gridid bigint,centerlng double,centerlat double,gridx int,gridy int,minlng double,maxlng double,minlat double,maxlat double)并且栅格的为一个边长为5m的正方形,其中:

gridid       :栅格id
centerlng:栅格中心点经度
centerlat :栅格中心点纬度
gridx        :栅格x轴方向的坐标位置
gridy        :栅格y轴方向的坐标位置

需求:给my_latlng表找它所落的栅格的id,如果my_latlng中的经纬度,在总体栅格以外,就不参与运算。

  • 解决方案一:

由于栅格有最大、最小经纬度,因此可以直接使用栅格的经纬度范围来给my_latlng表回填栅格id:

select t11.gridid,t10.lat,t10.lng
from my_latlng t10 inner join my_grid t11
where t10.lat>=t11.minlat and t10.lat<=t11.maxlat
and t10.lng>=t11.minlng and t10.lng<t11.minlng;

缺陷:该种方案缺陷inner join 是没有on条件的,如果在hive中是没有办法把>=,>,<,<=符号给写到inner join 中 on条件上的,语法问题吧。

因此,上边这条语句是执行的一个cross join,如果my_latlng表有1000wt条记录,而my_grid有10000w条记录时,这样的一个cross join 在加上 where条件,就会导致这个数据在集群中1000spark套餐(假设说1spark套餐:1vcore cpu+12g memory+500g disk。),5个小时也无法分析出结果。

  • 解决方案二:

我们知道经纬度小数点第5位代表的基本就是米单位,纬度30°时,经度每变化0.00001相当于变化1.1m。因此,我们可以粗略的认为5m的栅格在经度、纬度上的变化为0.00005个单位的变化。

因此,利用上边的这个特性我们可以有以下方案:

第一步、可以找到某些栅格距离自己纬度和经度变化接近5m的周围8+1个左右的栅格;

(
rpad(t10.lat+0.00005,7,‘0‘)=rpad(t11.centerlat,7,‘0‘)
or rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat+0.00005,7,‘0‘)
or rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat,7,‘0‘)
)
and
(
rpad(t10.lng+0.00005,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)
or rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng+0.00005,8,‘0‘)
or rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)
)

备注:我们计算范围:经度范围100.0到180.0,纬度范围为:10.0到90.0。

第二步、从第一步中的栅格中挑选距离自己最近的一个栅格作为自己归属栅格。

((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) distans

但是上边的程序如果放在hive中的语句因该是这么写:

select t11.gridid,t10.lat,t10.lng,(  (cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)  +(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) distans
from my_latlng t10 inner join my_grid t11
where (
  rpad(t10.lat+0.00005,7,‘0‘)=rpad(t11.centerlat,7,‘0‘)
  or rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat+0.00005,7,‘0‘)
  or rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat,7,‘0‘)
)
and(  rpad(t10.lng+0.00005,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)
  or rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng+0.00005,8,‘0‘)
  or rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)
);

但是上边的程序是有以下两个问题:

问题1)inner join 没有 on 条件,原因是where中语句不允许写到on中,也是hive的语法问题;

问题2)上边这段代码也是执行的cross join,而此自然执行的也很慢。

好的事情是:

1)从这段代码中,我们是可以把多个语句拆分出9个语句,而且这9个语句是可以具有on条件的;

2)之后把9个语句分析的结果union   all后的结果,再进行按照my_latlng.lat,my_latlng.lng分组求出具体每个经纬度的最小距离值;

3)使用“my_latlng的经纬度+最小距离”与“union all后的结果”进行一次inner join,就可以得到具体每个经纬度对应的栅格id。

具体代码:

hiveContext.sql("create table my_latlng_gridid_distance(gridid bigint,lat string,lng string,distance decimal(38,5))")
hiveContext.sql("create table my_latlng_mindistance(lat string,lng string,min_distans decimal(38,5))")
hiveContext.sql("create table my_latlng_gridid_result(gridid bigint,lat string,lng string)")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat+0.00005,7,‘0‘)=rpad(t11.centerlat,7,‘0‘) and (rpad(t10.lng+0.00005,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)").registerTempTable("temp00")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp00")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat+0.00005,7,‘0‘)=rpad(t11.centerlat,7,‘0‘) and rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng+0.00005,8,‘0‘)").registerTempTable("temp01")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp01")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat+0.00005,7,‘0‘)=rpad(t11.centerlat,7,‘0‘) and rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)").registerTempTable("temp02")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp02")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat+0.00005,7,‘0‘) and (rpad(t10.lng+0.00005,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)").registerTempTable("temp10")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp10")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat+0.00005,7,‘0‘) and rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng+0.00005,8,‘0‘)").registerTempTable("temp11")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp11")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat+0.00005,7,‘0‘) and rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)").registerTempTable("temp12")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp12")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat,7,‘0‘) and (rpad(t10.lng+0.00005,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)").registerTempTable("temp20")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp20")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat,7,‘0‘) and rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng+0.00005,8,‘0‘)").registerTempTable("temp21")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp21")

hiveContext.sql("select t11.gridid,t10.lat,t10.lng,cast(((cast(t10.lng as double)-t11.centerlng)*(cast(t10.lng as double)-t11.centerlng)+(cast(t10.lat as double)-t11.centerlat)*(cast(t10.lat as double)-t11.centerlat)) *10000000000000 as decimal(38,5)) distans from my_latlng t10 inner join my_grid t11 on rpad(t10.lat,7,‘0‘)=rpad(t11.centerlat,7,‘0‘) and rpad(t10.lng,8,‘0‘)=rpad(t11.centerlng,8,‘0‘)").registerTempTable("temp22")
hiveContext.sql("insert into my_latlng_gridid_distance select * from temp22")

hiveContext.sql("select lat,lng,min(distans) as min_distans " +
"from my_latlng_gridid_distance " +
"group by lat,lng").repartition(200).persist().registerTempTable("temp_10000")
hiveContext.sql("insert into my_latlng_mindistance select * from temp_10000")

hiveContext.sql("select t11.gridid,t11.lat,t11.lng " +
"from my_latlng_mindistance as t10 " +
"inner join my_latlng_gridid_distance as t11 " +
"on t10.lat=t11.lat and t10.lng=t11.lng and t10.min_distans=t11.distans")
.distinct() // must use distinct
.repartition(200).persist().registerTempTable("temp_20000")
hiveContext.sql("insert into my_latlng_gridid_result select * from temp_20000")
时间: 2024-08-02 06:48:12

给定了经纬度的一张my_latlng表,和一个栅格my_grid表,怎么实现my_latlng表回填栅格id?的相关文章

OrmLite动态创建表,一个实体类创建多张表的的偏招

在做一个Android的项目,因为使用数据库频繁,实体字段也比较多,于是打算采用ORM框架,发现OrmLite还不错,于是下了下来,打算使用. 没想到还没正式开工,就遇到问题了.我现在的一个需求如下, 我有一个实体类如下,代表聊天消息,现在要做的是针对每一个当前用户(userId)对应一个朋友(friendId)都要创建一个表.需求比较蛋疼,我本来想的是直接在加两个字段就搞定的,但是我们老大说要分表.没办法只能分表. public class ChatMessage{ public ChatMe

一张表保存一个无限级树形目录

一张表保存一个无限级树形目录: /****** Object: Table [dbo].[TreeMenue] Script Date: 08/20/2014 18:03:00 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [dbo].[TreeMenue]( [ID] [int] IDENTITY(1,1) NOT NULL, [MenueName] [v

Mysql数据库一个小程序实现自动创建分表。

每当跨月的时候也是系统出问题最多的时候,没有表和字段缺失是两个最常见的错误. 为了解决这个问题,研究了一下mysql的 information_schema 表: information_schema这张数据表保存了MySQL服务器所有数据库的信息.如数据库名,数据库的表,表栏的数据类型与访问权限等. 再简单点,这台MySQL服务器上,到底有哪些数据库.各个数据库有哪些表,每张表的字段类型是什么,各个数据库要什么权限才能访问,等等信息都保存在information_schema表里面. OK!事

spool命令、创建一个表,创建并且copy表,查看别的用户下的表,rowid行地址 索引的时候使用,表的增删改查,删除表,oracle的回收站

  1.spool命令 spool "D:\test.txt" spool off SQL> host cls 2.创建一个表 SQL> --条件(1):有创建表的权限,(2):有表空间 SQL> desc t4; 名称                                      是否为空? 类型 ----------------------------------------- -------- ------------------------

(转)数据库表分割技术浅析(水平分割/垂直分割/库表散列)

数据库表分割技术包含以下内容:水平分割/垂直分割/库表散列.接下来将对以上分割进行详细介绍,感兴趣的朋友可以了解下,对你日后维护数据库是很有帮助的 一.水平分割 什么是水平分割?打个比较形象的比喻,在食堂吃饭的时候,只有一个窗口,排队打饭的队伍太长了,都排成S型了,这时容易让排队的人产生焦虑情绪,容易产生混乱,这时一个管理者站出来,增加多个打饭窗口,把那条长长的队伍拦腰截断成几队.更形象一点的理解,你拿一把“手术刀”,把一个大表猛的切了几刀,结果这个大表,变成了几个小表. 水平分割根据某些条件将

利用反射处理多个表结构相同的数据的查询和数据库表的关联

最近做一个项目,需要对人口数据进行查询,但是人口数据分布在不同的街道表中,首先进行了数据表结构的统一,每个数据表以街道名开头,然后其他的名字都一样 前期将各个表中的字段也进行了统一 抽象出一张字典表 将街道编号和街道的名字的首字母连接起来,因为查询的时候是利用街道编号来的,这样可以根据街道标号拼出相对于的街道表的名字,(每个人口相关的表不止一张,因此需要统一):在查询过程中,将查询到的结构返回一个LIST,(不同的表在dao中当然对于不同的类啊,返回来再判断是哪一类),然后利用反射Field[]

表设计的原则与方法分析:追求表价值的最大化

表设计的原则与方法分析:追求表价值的最大化 在对象关系映射的应用系统设计中,对象就是表.对象关系即表关系,脱离对象设计表是错误的.对象的存在或价值在于它与其他对象的关系(设计研究的就是怎样处理对象以及对象之间的关系),不与其他对象产生关系的对象,或者说不与其他表有关系的表是没有价值的,不应创建. 当需求确定開始对系统进行设计时,首先进行对象分析.每个对象应具有唯一性,即对象的属性和方法唯一,能够明白的代表现实世界中的一种对象,因此与该对象相应的表的字段也具备唯一性.即在其它表中不应有反复字段.

(转载)数据库表分割技术浅析(水平分割/垂直分割/库表散列)

一.数据库表分割技术 数据库表分割技术包含以下内容: 水平分割 垂直分割 库表散列 1.1.水平分割 什么是水平分割?打个比较形象的比喻,在食堂吃饭的时候,只有一个窗口,排队打饭的队伍太长了,都排成S型了,这时容易让排队的人产生焦虑情绪,容易产生混 乱,这时一个管理者站出来,增加多个打饭窗口,把那条长长的队伍拦腰截断成几队.更形象一点的理解,你拿一把“手术刀”,把一个大表猛的切了几刀,结果这个大表,变成了几个小表. 水平分割根据某些条件将数据放到两个或多个独立的表中.即按记录进分分割,不同的记录

MySQL多表关联查询效率高点还是多次单表查询效率高,为什么?

MySQL多表关联查询效率高点还是多次单表查询效率高,为什么? <阿里巴巴JAVA开发手册>里面写超过三张表禁止join 这是为什么?这样的话那sql要怎么写? 原文地址:https://www.cnblogs.com/gotodsp/p/10090382.html