Postgresql奇怪的结果有条款

时间:2014-06-05 05:54:45

标签: sql postgresql

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

1 个答案:

答案 0 :(得分:2)

猜测,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来表示财务和确切数量,永远不会浮点数。