带有decimal / float比较的sqlite select查询不起作用

时间:2011-04-06 23:29:40

标签: sqlite decimal

我需要使用简单的select执行十进制比较操作,例如:

从table_a中选择*,其中时间> 0.0004

id time


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

结果包含满足比较的值。简而言之,“time> 0.0004”总是计算为true,“time< 0.0004”总是计算为false。

我尝试过铸造并将时间列的类型从十进制更改为float而没有成功。

如果我使用子查询,它会正确执行查询:

从table_a中选择*,其中时间> (从table_a中选择时间,其中id = 8);

id time


0 0.000502
1 0.000745
2 0.000725
6 0.000833

表格创建:

CREATE TABLE“table_a”(“id”整数NOT NULL PRIMARY KEY,“time”decimal NOT NULL);

5 个答案:

答案 0 :(得分:5)

感谢你的所有建议,我找到了问题的根源:

“时间”列值被视为“文本”。为什么?

我使用“.import”将数据导入到表中,我的CSV文件包含小数值周围的空格。不知何故,SQLite的import命令允许插入即使类型不匹配也会发生。从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 :(得分:4)

SQLite有一个非正统的动态类型系统,其中列的类型不确定列中实际数据的类型,它只是鼓励SQLite将数据转换为特定类型(如果可能的话)。 / p>

当尝试比较字符串和数字时,如果字符串不是格式良好的数字,那么它被认为大于数字。

所以一个明显的猜测是,由于某种原因,这些时间值实际上不是数字而是字符串。令人费解的是有两个原因。 (1)由于time列的类型为decimal,因此它应具有“数字”亲和力,它应该在其中存储任何看起来像转换为数字的数字。 (2)即使将值存储为字符串,它们仍应转换为数字,以便与0.0004进行比较。

为什么他们没有被转换?可能性#1:可能它们包含额外的空格或类似的东西。可能性#2:也许你的语言环境想要使用.之外的其他内容作为小数点。 (可能还有其他一些我没有想过的可能性。)

如果您在表中插入实际包含数字的记录 - insert into table_a (id,time) values (999,0.0001)或某种类型的记录 - 该记录是否包含在您的选择中?

答案 2 :(得分:2)

老问题,但我想给出另一个答案。

因为SQLite倾向于将所有内容都视为文本,所以会发生以下情况:

如果您查询... where a < 1000,如果将其视为文本

,它将永远不会找到任何内容

如果您查询... where a < '1000',它会将千分之一作为某种文本进行比较,如果数字具有不同的字符长度则会出现问题。 1000是4个字符,100个是3等

但是有CAST表达式http://www.sqlite.org/lang_expr.html#castexpr

所以... where cast(a as Integer) < 1000会产生你想要的东西(可以用REAL来完成浮动)

答案 3 :(得分:1)

显然,这不是你的情况,但请记住,有时某些管理工具(如SQLite AdministratorSQLite Expert)可能会向您显示实际值,尽管它们不是。这是一个例子:

Number Comparison

差别很小,但可能足以让你头疼。

答案 4 :(得分:0)

我无法重现您看到的行为。即使我

,我也能得到正确的结果
  • 将时间列定义为varchar,
  • 在单引号中插入值,
  • 在双引号内插入值,
  • 将时间列定义为十进制和 首先插入文本文字('test text')

但是,和Samuel Neff一样,我仍然希望在您的数据库中看到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