【问题标题】:Postgresql weird result on having clausePostgresql 有子句的奇怪结果
【发布时间】:2014-07-25 23:57:02
【问题描述】:
SELECT
T . ID,
T . NAME,
T .feed_id,
T .status,
T .budget,
(
    SELECT
        COUNT (*)
    FROM
        segment
    WHERE
        segment.campaign_id = T . ID
) AS total_segments,
(
    SELECT
        SUM (revenue)
    FROM
        TRANSACTION
    WHERE
        TRANSACTION .campaign_id = T . ID
    AND TRANSACTION .status = 3
    AND deleted = 0
) AS projected_revenue
  FROM
campaign T
 WHERE
(T .deleted = 0)
AND (site_id = 3)
GROUP BY
T ."id"
  HAVING
  (
    SELECT
        SUM (revenue)
    FROM
        TRANSACTION
    WHERE
        TRANSACTION .campaign_id = T . ID
    AND TRANSACTION .status = 3
    AND deleted = 0
    ) > 242.45
      ORDER BY
  T . ID DESC

having 子查询大于 (>) 或小于 (<) 时查询工作正常,但当等于时不显示任何结果。但它适用于:

HAVING (
  SELECT SUM (revenue)
  FROM TRANSACTION 
  WHERE TRANSACTION.campaign_id = T.ID 
    AND TRANSACTION.status = 3
    AND deleted = 0
)::NUMERIC = 242.45

【问题讨论】:

  • 会不会是 NUMERIC 类型说明符可以让您在小区间内进行比较? (242.45 不能表示为有限二进制数。)
  • @GáborBakos NUMERIC 是二进制编码的十进制。

标签: sql postgresql


【解决方案1】:

猜测revenuefloat4float8,即floatdouble precision 值。

正如@GáborBakos 准确指出的那样,某些值(包括 242.45)没有精确的二进制浮点表示。观察:

regress=> SET extra_float_digits = 3;
SET
regress=> SELECT FLOAT4 '242.45';
   float4   
------------
 242.449997
(1 row)

一般来说,您不应该比较浮点值是否相等。请改用小范围。

见:

您的查询与转换为 NUMERIC 一起工作,因为与 float4float8 不同,NUMERIC 是具有任意精度和小数位数的二进制编码的十进制类型。它可以精确地表示242.45,并且不会受到舍入伪像和浮点数学的其他怪异的影响。然而,这种演员阵容并不总是足够的 - 其他值可能仍然无法按您的预期工作。考虑:

regress=> select (float4 '0.3' * 100000000) :: NUMERIC;
     numeric      
------------------
 30000001.1920929
(1 row)

如您所见,这些舍入误差会累积。

与其依赖于与numeric 进行比较,不如真正使用小范围的比较,而不是进行相等性比较。或者,最重要的是,始终使用numeric 来表示财务和确切数量,从不浮点数。

【讨论】:

猜你喜欢
  • 2014-06-23
  • 1970-01-01
  • 2015-09-07
  • 2011-07-07
  • 1970-01-01
  • 2016-05-24
  • 2017-02-26
  • 2016-11-28
  • 2012-12-16
相关资源
最近更新 更多