2015-04-22 2 views
1

Этот запрос возвращает 1.7763568394002505e-15, когда он должен вернуться 0.00:SQLite проблема с плавающей точкой

SELECT st.id 
, Sum(
    CASE sa.Type 
    WHEN 4 THEN sa.quantity * (st.price - st.commission) 
    WHEN 5 THEN -sa.quantity * (st.price - st.commission) 
    ELSE 0.0 END 
) Sales 
FROM sales sa 
JOIN stock st 
    ON sa.stockid = st.id 
WHERE st.id = 1 
GROUP BY st.id 

http://sqlfiddle.com/#!5/cccd8/3

Это выглядит как классический вопрос расчета с плавающей точкой, но как я могу это исправить? Я пробовал отличать различные столбцы до REAL, но это не имеет значения.

Вы можете имитировать результат, используя этот запрос: РЕАЛЬНЫЙ

SELECT 26.3 - 10.52 - 15.78 AS Result 

ответ

2

SQLite не подходит для валюты. SQlite не поддерживает SQL-данные с десятичными или SQL-числами, поэтому наилучшим вариантом является использование целого числа и сохранение значений в виде центов.

CREATE TABLE stock (
    id INTEGER, 
    -- Store price and commission as integers, implying that price is in cents, 
    -- ($3.20 is stored as 320) and commission is a two-digit percentage (0.57% 
    -- is stored as 57). This is how scaled integers work in general. 
    price integer, 
    commission integer, 
    PRIMARY KEY(id) 
); 

CREATE TABLE sales (
    id INTEGER, 
    stockid INTEGER, 
    type INTEGER, 
    quantity INTEGER, 
    PRIMARY KEY(id) 
); 

insert into stock values (1, 320, 57); 
insert into sales values (1, 1, 4, 10); 
insert into sales values (2, 1, 5, 4); 
insert into sales values (3, 1, 5, 6); 

Этот запрос, от вашего SQLfiddle, правильно возвращает 0.

SELECT st.id 
, Sum(
    CASE sa.Type 
    WHEN 4 THEN sa.Quantity * (st.price - st.commission) 
    WHEN 5 THEN -sa.Quantity * (st.price - st.commission) 
    ELSE 0.0 END 
) Sales 
FROM sales sa 
JOIN stock st 
    ON sa.stockid = st.id 
WHERE st.id = 1 
GROUP BY st.id; 
 
id   Sales 
---------- ---------- 
1   0 

Кастинг в более подходящий тип данных (не к реальным) будет скрыть некоторые problems-- возможно, даже большинство проблем или даже всех из них в конкретном приложении. Но литье не будет решить их, потому что сохраненные значения могут отличаться от значений, которые вы действительно хотите.

1

Mike Sherrill верен тем, что вы, вероятно, должны использовать целые числа. Но для быстрого и грязного исправления вы можете обернуть звонок Sum в Round(__,2) до раунда до ближайшего цент.

Смежные вопросы