2011-04-06 134 views
4

我需要用一個簡單的選擇來進行十進制比較操作,例如:sqlite的選擇查詢不起作用

SELECT * FROM表-A,時間> 0.0004

ID時間


0 0.000502
1 0.000745
2 0.000725
4 0.000197
5 0.000176
6 0.000833
7 0.000269
8 0.000307
9 0.000302

結果包含做滿足比較條件的值。簡而言之,「時間> 0.0004」總是評估爲真,並且「時間< 0.0004」總是評估爲假。

我已經嘗試鑄造和更改時間列的類型從小數到浮動沒有成功。

如果我使用子查詢,它正確地執行查詢:

SELECT * FROM表-A,其中時間>(來自表-A選擇時間其中id = 8);

ID時間


0 0.000502
1 0.000745
2 0.000725
6 0.000833

表創建:

CREATE TABLE 「表-A」( 「ID」 整數NOT NULL PRIMARY KEY,「time」decimal NOT NULL);

+0

什麼'SELECT id,time,typeof(time)FROM table_a'返回? – 2011-04-07 00:17:13

+0

typeof(time)返回所有行的「text」。我使用「.import」命令來加載表,看起來這是問題。如果我使用「INSERT」插入記錄,則值的類型是「真實」而不是「文本」。 – 2011-04-07 18:29:24

+0

感謝您發佈數據如何作爲文本插入的詳細說明。有時候,如果你不注意那些數據類型錯誤,SQLite有點棘手。就個人而言,我們所有的模式都對列進行了「檢查」約束,以實施特定的數據類型。 – 2011-04-11 11:42:16

回答

3

SQLite有一個非傳統的動態類型系統,其中列的類型不確定列中實際數據的類型,它只是鼓勵SQLite在這種情況下可以將數據轉換爲特定類型。

當試圖比較一個字符串和一個數字時,如果該字符串不是一個格式良好的數字,那麼它被認爲大於數字。

所以一個明顯的猜測是,由於某些原因,這些時間值實際上並不是數字,而是字符串。這令人困惑的原因有兩個。 (1)由於time列的類型爲decimal,因此它應該具有「數字」關聯性,它應該獲取存儲在其中的任何內容,看起來像轉換爲數字的數字。 (2)即使這些值是作爲字符串存儲的,它們仍然應該被轉換爲數字,以便與0.0004進行比較。

爲什麼他們沒有被轉換?可能性#1:也許他們包含額外的空間或類似的東西。可能性#2:也許你的區域設置想使用.以外的值作爲小數點。 (可能還有其他的可能性,我沒有想到。)

如果您向表中插入一條實際包含數字的記錄 - insert into table_a (id,time) values (999,0.0001)或某種類型的記錄 - 是否包含在您的選擇中?

+0

選擇中包含0.0001的INSERT。看到我對Samuel Neff的回答。 – 2011-04-07 18:36:13

0

我無法重現您看到的行爲。我得到正確的結果,即使我

  • 定義時間欄爲varchar,單引號內
  • 插入值,雙引號內
  • 插入值,
  • 定義時間列小數和 首先插入文本文字(「測試文本」)

但是,像塞繆爾·內夫,我還是想看看你的數據庫的SELECT id, time, typeof(time) FROM table_a;結果。你知道還有什麼可能有趣嗎?

select * from table_a order by time; 

這些結果來自版本3.7.4,可能不是當前版本。

sqlite> .dump table_a 
PRAGMA foreign_keys=OFF; 
BEGIN TRANSACTION; 
CREATE TABLE "table_a" ("id" integer NOT NULL PRIMARY KEY, "time" decimal NOT NULL); 
INSERT INTO "table_a" VALUES(1,0.4); 
INSERT INTO "table_a" VALUES(2,0.6); 
INSERT INTO "table_a" VALUES(3,0.0005); 
INSERT INTO "table_a" VALUES(4,0.0006); 
INSERT INTO "table_a" VALUES(5,0.0004); 
COMMIT; 

sqlite> select * from table_a where time < 0.0005; 
5|0.0004 

sqlite> SELECT id, time, typeof(time) FROM table_a; 
1|0.4|real 
2|0.6|real 
3|0.0005|real 
4|0.0006|real 
5|0.0004|real 
+1

「ORDER BY time」確實會返回一個有序的結果。但是,我運行了你的交易,選擇工作正常。我認爲問題在於我使用「.import」來加載表格。我會做更多的測試併發布我的結果。 – 2011-04-07 18:38:18

+0

我確定它會被訂購。我不確定它會*數字*訂購。 – 2011-04-07 21:16:17

4

感謝您的建議,我已經找到了問題的根源:

「時間」欄值被處理爲「文本」。爲什麼?

我正在使用「.import」將數據導入到表中,並且我的CSV文件包含十進制值周圍的空格。不知何故,即使類型不匹配,SQLite的導入命令也允許插入。在我從CSV文件中刪除空格之後,數據被插入爲「真實」,這允許數字比較正確發生。然而,這並不能解釋爲什麼在「小數」列中的數據類型是「實」,而不是「十進制」或「數字」在他們的文檔解釋:http://www.sqlite.org/datatype3.html

select id, time, typeof(time) from table_a; 
id time   type 
---- ------------- ---- 
0  0.000502  text 
1  0.000745  text 
2  0.000725  text 
4  0.000197  text 
5  0.000176  text 
6  0.000833  text 
7  0.000269  text 
8  0.000307  text 
9  0.000302  text 

select id, time, typeof(time) from table_b; 
id time   type 
---- ------------- ---- 
0  0.000502  real 
1  0.000745  real 
2  0.000725  real 
4  0.000197  real 
5  0.000176  real 
6  0.000833  real 
7  0.000269  real 
8  0.000307  real 
9  0.000302  real 
+1

啊哈,空格。告訴過你。 :-)至於類型:「decimal」和「numeric」是SQLite中的列類型,但不是數據類型。他們告訴SQLite哪些轉換嘗試列中的數據,但它們本身並不是數據的可能類型。再看看你鏈接到的那個頁面。 – 2011-04-07 21:24:24

2

老問題,但我想給出另一個答案。

因爲SQLite的往往看到的一切文本,會發生以下情況:

如果查詢... where a < 1000如果作爲文本

如果查詢... where a < '1000'將比較單處理它永遠不會發現什麼千作爲某種文本,並且如果數字具有不同的字符長度,則會出現問題。 1000是4個字符,100是3等

但有科協表達http://www.sqlite.org/lang_expr.html#castexpr

所以... where cast(a as Integer) < 1000將導致你想要什麼(可以OFC與REAL做了花車)

1

很明顯:這不是什麼請記住,有時某些管理工具(如SQLite AdministratorSQLite Expert)可能會顯示您的實際值相同,但它們不是。這裏有一個例子:

Number Comparison

不同的是未成年人,但大概是足以讓你硬頭痛。