2011-04-06 94 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

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