带有小数/浮点比较的 sqlite select 查询不起作用
我需要使用简单的 select 来执行十进制比较操作,例如:
select * from table_a where time > 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
结果包含满足比较的值。简而言之,“time > 0.0004”始终评估为 true,“time < 0.0004”始终评估为 false。
我尝试将时间列的类型从十进制转换为浮点数,但没有成功。
如果我使用子查询,它会正确执行查询:
select * from table_a where time > (从 table_a 中选择时间,其中 id=8);
ID 时间
0 0.000502
1 0.000745
2 0.000725
6 0.000833
表创建:
CREATE TABLE "table_a" ("id" 整数 NOT NULL PRIMARY KEY, "time" 小数 NOT NULL);
I need to perform decimal comparison operations using a simple select, for example:
select * from table_a where time > 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
The result contains values that do satisfy the comparison. In a few words, "time > 0.0004" always evaluates to true, and "time < 0.0004" always evaluates to false.
I have tried casting and changing the type of the time column from decimal to float without success.
If I use a subquery, it performs the query correctly:
select * from table_a where time > (select time from table_a where id=8);
id time
0 0.000502
1 0.000745
2 0.000725
6 0.000833
Table create:
CREATE TABLE "table_a" ("id" integer NOT NULL PRIMARY KEY, "time" decimal NOT NULL);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
感谢您的所有建议,我找到了问题的根源:
“时间”列值被作为“文本”处理。为什么?
我使用“.import”将数据导入到表中,而我的 CSV 文件在小数值周围包含空格。不知何故,即使类型不匹配,SQLite 的导入命令也允许插入发生。从 CSV 文件中删除空格后,数据将作为“真实”插入,这样可以正确进行数字比较。但是,它没有解释为什么“十进制”列中的数据是“实数”类型,而不是“十进制”或“数字”,如其文档中所述: http://www.sqlite.org/datatype3.html
Thanks to all your suggestions, I have found the root of the problem:
The "time" column values were being handled as "text". Why?
I was importing data to the table using ".import" and my CSV file contained spaces around the decimal values. Somehow, SQLite's import command allows the inserts to happen even if the types do not match. After I removed the spaces from the CSV file, the data is inserted as "real", which allows for the number comparisons to happen correctly. HOWEVER, it does not explain why the data in the "decimal" column is of type "real" and not "decimal" or "numeric" as explained in their docs: http://www.sqlite.org/datatype3.html
SQLite 有一个非正统的动态类型系统,其中列的类型并不决定列中实际数据的类型,它只是鼓励 SQLite 将数据转换为特定类型(如果可能的话)。
当尝试比较字符串和数字时,如果字符串不是格式正确的数字,则它被认为大于数字。
因此,一个明显的猜测是,由于某种原因,这些时间值实际上不是数字,而是字符串。这令人费解有两个原因。 (1) 由于
time
列的类型为decimal
,因此它应该具有“数字”亲和性,这应该将存储在其中的任何看起来像数字的内容转换为数字。 (2) 即使值存储为字符串,它们仍应转换为数字以与 0.0004 进行比较。为什么他们没有归信呢?可能性#1:也许它们包含额外的空格或类似的东西。可能性#2:也许您的语言环境想要使用
.
之外的其他内容作为小数点。 (很可能还有其他我没有想到的可能性。)如果您在表中插入一条实际上包含数字的记录 -
insert into table_a (id,time)values (999,0.0001) 或类似的东西 - 该记录是否包含在您的选择中?
SQLite has an unorthodox dynamic-typing system where the type of a column doesn't determine the type of the actual data in the column, it merely encourages SQLite to convert data to a particular type if that happens to be possible.
When trying to compare a string and a number, if the string isn't a well-formed number then it's considered greater than the number.
So an obvious guess is that for some reason these time values aren't actually numbers but strings. That's puzzling for two reasons. (1) Since the
time
column has typedecimal
, it should have "numeric" affinity, which should get anything stored in it that looks like a number converted to be a number. (2) Even if the values were stored as strings, they should still have been converted to numbers for comparing against 0.0004.Why might they not have been converted? Possibility #1: maybe they contain extra spaces or something of the sort. Possibility #2: maybe your locale wants to use something other than
.
as the decimal point. (There may well be other possibilities that I haven't thought of.)If you insert a record into the table that actually contains a number --
insert into table_a (id,time) values (999,0.0001)
or something of the sort -- does that record get included in your selection?老问题,但我想给出另一个答案。
因为 SQLite 倾向于将所有内容视为文本,所以会发生以下情况:
如果您查询
... 其中 a < a 被视为文本,它将永远找不到任何内容
1000如果您查询
... 其中 a
如果 '1000'
它将把千作为某种文本进行比较,如果数字具有不同的字符长度,则会出现问题。 1000 是 4 个字符,100 是 3 个字符,等等但是有 CAST 表达式 http://www.sqlite。 org/lang_expr.html#castexpr
所以
... 其中cast(a as Integer) < 1000
将得到你想要的结果(ofc可以用REAL来完成浮点数)Old question but i want to give another answer.
Because SQLite tends to see everything as text, the following happens:
If you query
... where a < 1000
it will never find anything if a is treated as textif you query
... where a < '1000'
it will compare the one-thousand as some sort of text and has issues if the numbers have different character lenght. 1000 is 4 chars and 100 is 3 etcBut there is the CAST expression http://www.sqlite.org/lang_expr.html#castexpr
so
... where cast(a as Integer) < 1000
will result in what you want (can ofc be done with REAL for floats)我无法重现您所看到的行为。即使我
首先插入文本文字(“测试文本”)
但是,像 Samuel Neff 一样,我仍然希望在数据库中查看 SELECT id, time, typeof(time) FROM table_a; 的结果。你知道还有什么可能有趣吗? 这些结果
来自版本 3.7.4,可能不是当前版本。
I can't reproduce the behavior you see. I get the right results even if I
insert text literals first ('test text')
But, like Samuel Neff, I'd still like to see the result of
SELECT id, time, typeof(time) FROM table_a;
in your database. You know what else might be interesting? The result ofThese results are from version 3.7.4, which might not be the current version.
显然这不是你的情况,但请记住,有时一些管理工具(例如 SQLite Administrator 或 < a href="http://www.sqliteexpert.com/" rel="nofollow noreferrer">SQLite Expert)可能会向您显示实际值相等,但事实并非如此。这是一个示例:
差异很小,但可能足以让您头疼。
Obviously it wasn't your case, but keep in mind that sometimes some administration tools (like SQLite Administrator or SQLite Expert) may show you real values as equal, although they are not. Here's an example:
The difference is minor, but is probably enough to give you a hard headache.