您
HAVINg的处理方式正确,但是您传递的是错误的表达式。似乎您正在使用Python 2,因为字符串和整数之间的关系比较
'distance' < 25
不会引发异常,而是求值为
False。换句话说,您的查询等于
locations = db.session.query(...).having(False).all()
这就解释了为什么您得到零结果的原因:所有行都被HAVINg子句明确过滤掉了,如印刷版所示:
...HAVINg false = 1 -- remove all rows
一种解决方案是使用合适的构造,例如
column(),来产生表达式:
locations = db.session.query(...).having(column('distance') < 25).all()您不应将复杂的选择列表项表达式包装在
select()表示SELECT语句的中。标签
text()为:
text('( 6371 * acos( cos( radians("53.6209798282177") ) * ' 'cos( radians( lat ) ) * cos( radians( lng ) - radians("13.96948162900808") ) + ' 'sin( radians("53.6209798282177") ) * sin( radians( lat ) ) ) ) ' 'AS distance')或使用模型构建表达式:
(6371 * func.acos(func.cos(func.radians(53.6209798282177)) *func.cos(func.radians(Location.lat)) *func.cos(func.radians(Location.lng) - func.radians(13.96948162900808)) +func.sin(func.radians(53.6209798282177)) *func.sin(func.radians(Location.lat)))).label('distance')你可以通过使功能为提高查询建设的可读性大圆距离,并与工作的一点点,你可以实现一个混合方法上
Location:
import mathdef gc_distance(lat1, lng1, lat2, lng2, math=math): ang = math.acos(math.cos(math.radians(lat1)) * math.cos(math.radians(lat2)) * math.cos(math.radians(lng2) - math.radians(lng1)) + math.sin(math.radians(lat1)) * math.sin(math.radians(lat2))) return 6371 * angclass Location(db.Model): ... @hybrid_method def distance(self, lat, lng): return gc_distance(lat, lng, self.lat, self.lng) @distance.expression def distance(cls, lat, lng): return gc_distance(lat, lng, cls.lat, cls.lng, math=func)locations = db.session.query( Location, Location.distance(53.6209798282177, 13.96948162900808).label('distance')). having(column('distance') < 25). order_by('distance'). all()请注意,使用HAVINg消除非组行的方法不是可移植的。例如,在Postgresql中,即使没有GROUP
BY子句,HAVINg子句的存在也会将查询转换为分组查询。您可以改用子查询:
stmt = db.session.query( Location, Location.distance(53.6209798282177, 13.96948162900808).label('distance')). subquery()location_alias = db.aliased(Location, stmt)locations = db.session.query(location_alias). filter(stmt.c.distance < 25). order_by(stmt.c.distance). all()


