ClickHouse pointInPolygon函数地理坐标查询报错排查
报错根因
pointInPolygon 函数要求第一个入参必须是非Nullable类型的数值元组,不支持带Nullable属性的数值。
虽然你在WHERE条件中已经加了lat is not null and lon is not null的非空过滤逻辑,但ClickHouse的类型推导机制不会因为WHERE阶段的非空判断,自动把Tuple内部的Nullable(Float64)类型转换为非空Float64,最终传入函数的参数类型始终是Tuple(Nullable(Float64), Nullable(Float64)),不符合函数参数类型要求,因此抛出类型非法的错误。
另外你描述表结构时写的lon(Float65)为笔误,ClickHouse不存在Float65类型,浮点类型仅支持Float32、Float64两类。
修复方案
方案1:显式转换非空类型(无需改表结构)
在构造坐标点元组时,用assumeNotNull函数显式将lat、lon转为非空类型,由于你已经提前做了非空过滤,不会出现空值异常。修改后的完整查询语句如下:
select deviceId, lat, lon from `click-ss`.telemetry_data WHERE 1=1 and (lat is not null and lon is not null) and (lat != 0 and lon != 0) and fix='1' -- 定位时卫星数量足够 and toTimeZone(eventDt, 'Europe/Moscow') BETWEEN '2022-07-01 00:00:00' AND '2022-07-01 23:59:59' and pointInPolygon( tuple(assumeNotNull(lat), assumeNotNull(lon)), array( tuple(55.736916, 37.365922), tuple(55.791985, 37.367902), tuple(55.872216, 37.399581), tuple(55.918200, 37.564574), tuple(55.896698, 37.713728), tuple(55.825806, 37.847042), tuple(55.646882, 37.848362), tuple(55.566931, 37.682709), tuple(55.584878, 37.501877), tuple(55.714776, 37.382372) ) ) = 1
方案2:调整表字段属性(长期方案)
如果这两个坐标字段不需要存储空值,可以直接在建表时将lat、lon设置为非Nullable的Float64类型,从根源上避免类型不匹配问题。
使用注意事项
- 坐标顺序必须统一:你当前传入的点坐标是
(纬度, 经度)格式,要确保多边形所有顶点的元组也保持(纬度, 经度)的顺序,经纬度写反会导致判断结果完全错误。 - 多边形顶点需要按顺时针或逆时针的连续顺序传入,不要打乱顶点排列顺序,否则构造出的多边形形状不符合预期,判断结果会出现偏差。
内容的提问来源于stack exchange,提问作者Sick Monkey
相关产品推荐
相关产品推荐

