【问题标题】:Querying for floating point values in SQLAlchemy在 SQLAlchemy 中查询浮点值
【发布时间】:2014-05-15 23:03:53
【问题描述】:

总结一下这个问题,我不能使用 SQLAlchemy 选择针对浮点值的任何实体。

例如:

m = session.query(Model).get(1);
all_m = session.query(Model).filter(Model.some_float_value, m.some_float_value)

all_m 是空的,而我希望它总是至少有一个!

如何根据任意精度过滤 SQLAlchemy 中的浮点值(例如,我可能希望匹配 0.01 或其他我可能以 0.0005 的精度过滤)。

例如,我希望能够编写一个通用函数,这样我就可以在我的代码中编写这样的查询:

session.query(Model)\
    .filter(Model.foo == "bar",
            match_float(Model.some_float_value, float_val, 0.025)).all()

如果有公差匹配任何在 0.025 的近似公差范围内。

但是,我对 SQLAlchemy 不是很熟悉,并且无法找到有关如何创建自定义比较函数或任何可以满足我需要的内置函数的文档。

是否有我可以使用的内置函数、为过滤器方法提供自定义比较函数的方法,或者我是否可以为此编写原始查询/过程?

附加信息:

Postgres 9.2

SQLAlchemy 0.9

值存储为双精度浮点数

所有模型都是这样定义的(它们有很多,这使得具有显式列定义的解决方案不太理想):

engine = create_engine('postgresql://user:pass@localhost:1234/database')
Base = declarative_base()
metadata = MetaData(bind=engine)

class Model(Base):
    __table__ = Table('model', metadata, autoload=True)

编辑

为了清楚起见,我完全改写了我的问题。很抱歉造成混乱,我无法与人类交流......

【问题讨论】:

  • “匹配到 .01”对您意味着什么?
  • 这意味着匹配任何(abs(a-b)> = 0.01)
  • 或者换句话说,它只能与 45.06 比较。我可以很好地完成所有这些事情。 **我不知道该怎么做是编写一个函数,该函数返回过滤器函数中参数的有效匹配条件。 **

标签: python floating-point sqlalchemy


【解决方案1】:

GeoAlchemy 中显示了一个自定义比较的具体示例(尽管它可能对您的应用程序来说有点过分)。虽然下面链接中的示例使用边界框来比较空间坐标,但您可以使用更简单的方法在容差范围内实现比较。

请参见此处定义“~=”和其他运算符的 Comparator 类:

http://geoalchemy-2.readthedocs.org/en/0.2.4/spatial_operators.html

由于您提到无法找到有关如何实现自定义比较功能的文档,请参见此处:

http://docs.sqlalchemy.org/en/latest/core/types.html#types-operators

在相关说明中 - 如果您想防止在浮点列保持在某个阈值内时触发数据库更新,请参阅此处的讨论:

https://groups.google.com/forum/#!msg/sqlalchemy/tCpsGZmjk_w/lOwW93qHV0sJ

(免责声明:这是基于谷歌搜索,我是 SQLAlchemy 的新手)

【讨论】:

  • 感谢您的回复。更改 ORM 不是一种选择,但如果没有更好的解决方案,我最终可能会接受您对自定义类型运算符的建议作为不太理想的解决方案。模型数量众多,而且都有很多领域。如果没有自动生成的模式,维护和更新将非常困难。即使是注入原始查询的包装器函数也会是一个更好的解决方案,如果它可以在我需要的任何字段上通用。
  • “即使是注入查询的包装函数也会是一个更好的解决方案...” 变体怎么样:stackoverflow.com/questions/15936111/…>
  • 我相信那里的第一条评论仍然需要自定义类型覆盖。另外,您对覆盖的确切想法是什么?你的意思是我应该覆盖等于运算符并发送一个带有 (VALUE,PRECISION) 类型的东西的 touple 吗?第二条评论的链接断开。
  • 不确定链接发生了什么,这里又是:bitbucket.org/zzzeek/sqlalchemy/wiki/UsageRecipes/GlobalFilter
  • 我的意思是:你能继承 Query,添加一个新方法 inside_tolerance(self,epsilon,...) 吗?我不确定您仅限于哪些选项,所以我想强调添加全新方法的选项。我不认为这种方法需要自定义类型。
【解决方案2】:

浮点数的经验法则之一是“永远不要比较浮点数是否相等”。 (你可以谷歌那个报价。)

最简单和最可预测的方法是使用 SQL 十进制(n,m)数据类型而不是浮点数。 SQL decimal(n,m) 数据类型没有近似误差。

SQLAlchemy supports SQL decimals.

如果您必须使用双打操作,最好的选择可能是遵循C FAQ 推荐的两种方法之一。

计算不等式(abs(a-b) >= 0.01) 的一个问题是,将使用最接近a 和b 的浮点近似来计算结果。这些浮点近似值可能正是您期望的值,但这取决于应用程序。 (当分配给双精度时,十进制值 45.06 和 45.062 并不是您所期望的。换句话说,最接近 45.06 的浮点近似值不是 45.06。)

C 常见问题解答对使用这种表达式作为确定相等性的通用方法有一些话要说。

【讨论】:

  • 更准确地说,它可以精确地表示有限小数。十进制在表示 pi 或 1/3 方面并不比二进制好。
  • 感谢您的回复,我需要在可变进动处匹配双精度值,而不是在固定进动处匹配十进制字段。您能否提供有关我如何做到这一点的任何见解?
  • @PatriciaShanahan 这些值实际上是整数值的小数数学结果,因此您的评论非常相关。谢谢。
  • @drkstr1:更新答案。
  • 我很抱歉我的问题没有更清楚。我确切地知道浮点数是如何工作的。我需要知道如何在 SQLAlchemy 中查询它们。是否有我可以使用的内置函数,一种为过滤器方法提供自定义比较函数的方法,或者我是否需要为此使用原始查询?感谢您的宝贵时间!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
  • 1970-01-01
相关资源
最近更新 更多