下面就是round函數抽風的例子和替代的解決方案:
sqlite> select 5.75*0.9, round(5.75*0.9, 2), FLOOR( 5.75*100*0.9+0.5)/100.0;
+----------+--------------------+--------------------------------+
| 5.75*0.9 | round(5.75*0.9, 2) | FLOOR( 5.75*100*0.9+0.5)/100.0 |
+----------+--------------------+--------------------------------+
| 5.175 | 5.17 | 5.18 |
+----------+--------------------+--------------------------------+
1 row in set
sqlite> select 10.25*1.1, ROUND(10.25*1.1, 2), FLOOR(10.25*100*1.1+0.5)/100.0;
+-----------+---------------------+--------------------------------+
| 10.25*1.1 | ROUND(10.25*1.1, 2) | FLOOR(10.25*100*1.1+0.5)/100.0 |
+-----------+---------------------+--------------------------------+
| 11.275 | 11.28 | 11.28 |
+-----------+---------------------+--------------------------------+
1 row in set
有的情況下(python使用sqlalchemy時,在創建視圖時,如果視圖使用了FLOOR,視圖創建失敗),我們無法使用SQLite的FLOOR函數和CEIL函數,此時我們還有一種替代方案:先將REAL類型的數值轉換爲字符串,轉換後的字符串會有一個小數點,然後將小數點替換爲一個無效字符(比如下劃線'_'),然後再將其轉換爲數值,進行運算。
具體方案如下:
sqlite> select REPLACE(5.75*100*0.9+0.5, '.', '_')/100.0;
+-------------------------------------------+
| REPLACE(5.75*100*0.9+0.5, '.', '_')/100.0 |
+-------------------------------------------+
| 5.18 |
+-------------------------------------------+
1 row in set
其轉換過程大致是這樣的:
運算後的數是一個浮點數:
sqlite> select TYPEOF(5.75*100*0.9+0.5);
+--------------------------+
| TYPEOF(5.75*100*0.9+0.5) |
+--------------------------+
| real |
+--------------------------+
1 row in set
將其轉換爲字符串:
sqlite> select LOWER(5.75*100*0.9+0.5);
+-------------------------+
| LOWER(5.75*100*0.9+0.5) |
+-------------------------+
| 518.0 |
+-------------------------+
1 row in set
替換字符串中的小數點:
sqlite> select REPLACE(5.75*100*0.9+0.5, '.', '_');
+-------------------------------------+
| REPLACE(5.75*100*0.9+0.5, '.', '_') |
+-------------------------------------+
| 518_0 |
+-------------------------------------+
1 row in set
將替換後的字符串參與運算:
sqlite> select REPLACE(5.75*100*0.9+0.5, '.', '_')/100.0;
+-------------------------------------------+
| REPLACE(5.75*100*0.9+0.5, '.', '_')/100.0 |
+-------------------------------------------+
| 5.18 |
+-------------------------------------------+
1 row in set
sqlite>
因爲FLOOR函數得到的是一個integer,我們如果想模擬FLOOR函數,可以將替換後的字符串除以1,因爲沒有小數,SQLite就自動將其轉換爲integer了。如下所示:
sqlite> select REPLACE(5.75*100*0.9+0.5, '.', '_')/1;
+---------------------------------------+
| REPLACE(5.75*100*0.9+0.5, '.', '_')/1 |
+---------------------------------------+
| 518 |
+---------------------------------------+
1 row in set
可以看到,因爲除完之後沒有小數,它的類型直接變成了integer。
sqlite> select TYPEOF(REPLACE(5.75*100*0.9+0.5, '.', '_')/1);
+-----------------------------------------------+
| TYPEOF(REPLACE(5.75*100*0.9+0.5, '.', '_')/1) |
+-----------------------------------------------+
| integer |
+-----------------------------------------------+
1 row in set
而直接除100的話,因爲有小數,它的類型就變成了real。
sqlite> select TYPEOF(REPLACE(5.75*100*0.9+0.5, '.', '_')/100);
+-------------------------------------------------+
| TYPEOF(REPLACE(5.75*100*0.9+0.5, '.', '_')/100) |
+-------------------------------------------------+
| real |
+-------------------------------------------------+
1 row in set
用integer除以integer的話,就是取整了:
sqlite> select REPLACE(5.75*100*0.9+0.5, '.', '_')/1/100;
+-------------------------------------------+
| REPLACE(5.75*100*0.9+0.5, '.', '_')/1/100 |
+-------------------------------------------+
| 5 |
+-------------------------------------------+
1 row in set
sqlite> select TYPEOF(REPLACE(5.75*100*0.9+0.5, '.', '_')/1/100);
+---------------------------------------------------+
| TYPEOF(REPLACE(5.75*100*0.9+0.5, '.', '_')/1/100) |
+---------------------------------------------------+
| integer |
+---------------------------------------------------+
1 row in set
sqlite>
完。