Проблема сравнения реальных значений (с плавающей запятой) в Sqlite - PullRequest
0 голосов
/ 07 ноября 2019

Я делаю запрос на основе образца базы данных chinook.db (https://www.sqlitetutorial.net/sqlite-sample-database/) ниже, но результат странный.

-- SQLite version 3.30.1 2019-10-10 20:19:45
select
    Total,
    TotalSaleValue
from invoices
natural join (
    select
        InvoiceId,
        sum(UnitPrice) as TotalSaleValue
    from invoice_items
    group by InvoiceId
)
where Total != TotalSaleValue;

-- Output
Total       TotalSaleValue
----------  --------------
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
13.86       13.86
...

Я использую where Total != TotalSaleValue для фильтрации неравных значений, иЯ ожидаю получить пустую строку. Но результат показывает Total и TotalSaleValue с одинаковым значением?!

Total - это значение из таблицы invoices, а значение TotalSaleValue рассчитывается по таблице invoice_items, которая является суммой UnitPrice каждого счета.

-- invoice_items Table
InvoiceLineId  InvoiceId   TrackId     UnitPrice   Quantity
-------------  ----------  ----------  ----------  ----------
1              1           2           0.99        1
2              1           4           0.99        1
3              2           6           0.99        1
4              2           8           0.99        1
5              2           10          0.99        1
6              2           12          0.99        1
7              3           16          0.99        1
8              3           20          0.99        1
9              3           24          0.99        1
10             3           28          0.99        1
-- invoices Table
InvoiceId   ...         CustomerId  Total
----------  ----------  ----------  ----------
1           ...         2           1.98
2           ...         4           3.96
3           ...         8           5.94
4           ...         14          8.91
5           ...         23          13.86
6           ...         37          0.99
7           ...         38          1.98
8           ...         40          1.98
9           ...         42          3.96
10          ...         46          5.94

Кто-нибудь знает, что не так с моим запросом?

Обновление:

Я обнаружил, что результат будет правильным, если я приведу Total и TotalSaleValue к TEXT и дам псевдоним X и Y.

select
    cast(Total as text) as X,
    cast(TotalSaleValue as text) as Y
from invoices
natural join (
    select
        InvoiceId,
        sum(UnitPrice) as TotalSaleValue
    from invoice_items
    group by InvoiceId
)
where X != Y;

1 Ответ

0 голосов
/ 07 ноября 2019

Благодаря ссылке от @ Shwan

https://stackoverflow.com/a/588014/2802074

Результат будет правильным, если я использую abs(Total - TotalSaleValue) > 0.00001, чтобы избежать проблемы с плавающей запятой.

select
    Total,
    TotalSaleValue
from invoices
natural join (
    select
        InvoiceId,
        sum(UnitPrice) as TotalSaleValue
    from invoice_items
    group by InvoiceId
)
where abs(Total - TotalSaleValue) > 0.00001;

Сводка

Вместо использования WHERE x == y всегда используйте WHERE abs(x - y) < 0.00001 для сравнения РЕАЛЬНЫХ (с плавающей запятой) значений

...