as the title states:
I have a select query, which I'm trying to "order by" a field which contains numbers, the thing is this numbers are really strings starting with 0s, so the "order by" is doing this...
...
10
11
12
01
02
03
...
Any thoughts?
EDIT: if I do this: "...ORDER BY (field+1)" I can workaround this, because somehow the string is internally being converted to integer. Is this the a way to "officially" convert it like C's atoi?
You can use CAST http://www.sqlite.org/lang_expr.html#castexpr to cast the expression to an Integer.
sqlite> CREATE TABLE T (value VARCHAR(2));
sqlite> INSERT INTO T (value) VALUES ('10');
sqlite> INSERT INTO T (value) VALUES ('11');
sqlite> INSERT INTO T (value) VALUES ('12');
sqlite> INSERT INTO T (value) VALUES ('01');
sqlite> INSERT INTO T (value) VALUES ('02');
sqlite> INSERT INTO T (value) VALUES ('03');
sqlite> SELECT * FROM T ORDER BY CAST(value AS INTEGER);
01
02
03
10
11
12
sqlite>
if I do this: "...ORDER BY (field+1)" I can workaround this, because somehow the string is internally being converted to integer. Is the a way to "officially" convert it like C's atoi?
Well thats interesting, though I dont know how many DBMS support such an operation so I don't recommend it just in case you ever need to use a different system that doesn't support it, not to mention you are adding an extra operation, which can affect performance, though you also do this ORDER BY (field + 0) Im going to investigate the performance
taken from the sqlite3 docs:
A CAST expression is used to convert the value of to a different storage class in a similar way to the conversion that takes place when a column affinity is applied to a value. Application of a CAST expression is different to application of a column affinity, as with a CAST expression the storage class conversion is forced even if it is lossy and irrreversible.
4.0 Operators
All mathematical operators (+, -, *, /, %, <<, >>, &, and |) cast both operands to the NUMERIC storage class prior to being carried out. The cast is carried through even if it is lossy and irreversible. A NULL operand on a mathematical operator yields a NULL result. An operand on a mathematical operator that does not look in any way numeric and is not NULL is converted to 0 or 0.0.
I was curios so I ran some benchmarks:
>>> setup = """
... import sqlite3
... import timeit
...
... conn = sqlite3.connect(':memory:')
... c = conn.cursor()
... c.execute('CREATE TABLE T (value int)')
... for index in range(4000000, 0, -1):
... _ = c.execute('INSERT INTO T (value) VALUES (%i)' % index)
... conn.commit()
... """
>>>
>>> cast_conv = "result = c.execute('SELECT * FROM T ORDER BY CAST(value AS INTEGER)')"
>>> cast_affinity = "result = c.execute('SELECT * FROM T ORDER BY (value + 0)')"
>>> timeit.Timer(cast_conv, setup).timeit(number = 1)
18.145697116851807
>>> timeit.Timer(cast_affinity, setup).timeit(number = 1)
18.259973049163818
>>>
As we can see its a bit slower though not by much, interesting.
You could use CAST:
ORDER BY CAST(columnname AS INTEGER)
In ListView with cursor loader!
String projection= some string column;
String selection= need to select;
String sort="CAST ("+ YOUR_COLUMN_NAME + " AS INTEGER)";
CursorLoader(getActivity(), Table.CONTENT_URI, projection, selection, selectionArgs, sort);
CONVERT CAST function using order by column value number format in SQL SERVER
SELECT * FROM Table_Name ORDER BY CAST(COLUMNNAME AS INT);
Thanks to Skinnynerd. with Kotlin, CAST worked as follows:
CAST fix the problems of prioritizing 9 over 10 OR 22 over 206.
define global variable to alter later on demand, and then plug it in the query:
var SortOrder:String?=null
to alter the order use:
For descendant:
SortOrder = "CAST(MyNumber AS INTEGER)" + " DESC"
(from highest to lowest)
For ascending:
SortOrder = "CAST(MyNumber AS INTEGER)" + " ASC"
(from lowest to highest)
Related
I have a column that contains Sring data with numbers in them. the format of the number is like (x,xxx).
for example, the number 1555 is stored as 1,555
I want to order the data from the table. I have tried CAST AS
#Query("SELECT * from country_table ORDER BY CAST(cases AS INTEGER)")
fun getAllCountries(): LiveData<List<SingleCountryStats>>
but this doesn't work since the field can not be cast to integer due to the comma in the middle
is there any option to remove the commas then order the results?
If the commas are used consistently, you can use:
order by length(cases), cases
Otherwise, you can remove the commas and convert:
order by cast(replace(cases, ',', '') as int)
Remove the comma and sort the column as a number:
SELECT * from country_table ORDER BY REPLACE(cases, ',', '') + 0
The operator + casts implicitly the string to a number.
with a simple query, using bindargs works fine, but as soon as I include select case ..... in the query it always fails "Can't pass bindargs for this sql", if I test with all the '?'s replaced with fixed values, it compiles and runs OK, so it does seem to be that argument binding cannot cope with selects embedded inside select case. Is this true?
the query I am compiling is:
(SELECT CASE
WHEN ((SELECT _id FROM point2D WHERE x=? AND y=?) IS NULL ) THEN 0
ELSE (SELECT _id FROM point2D WHERE x=? AND y=? LIMIT 1))
and the table is setup with
create table if not exists point2D ( _id INTEGER PRIMARY KEY AUTOINCREMENT,
x REAL, y REAL )
I only want a single compiled query that returns the key to an existing matching record, or a known 'its not there' value, but of course a simple query like
SELECT _id FROM point2D WHERE x=? AND y=? LIMIT 1
will cause an exception with simpleQueryForLong when there is nothing found (which is quite expensive in cpu time)
I cannot use insert or update, because update actually replaces the old row with a new row (and hence a new _id) which screws up all the other stuff pointing to this.
You have kept the actual parameter code a secret, but I'd guess that you provide only two parameters although the query has four.
You can use one parameter multiple times if you give it a name or a number:
(SELECT CASE
WHEN ((SELECT _id FROM point2D WHERE x=?1 AND y=?2) IS NULL ) THEN 0
ELSE (SELECT _id FROM point2D WHERE x=?1 AND y=?2 LIMIT 1))
However, for this particular query, you'd better use the ifnull function:
(SELECT ifnull((SELECT _id FROM point2D WHERE x=? AND y=?), 0))
(And I doubt that the outer subquery is actually needed.)
I want to select records from sqlite3 database by string matching. But if I use '=' in the where clause, I found that sqlite3 is case sensitive. Can anyone tell me how to use string comparing case-insensitive?
You can use COLLATE NOCASE in your SELECT query:
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
Additionaly, in SQLite, you can indicate that a column should be case insensitive when you create the table by specifying collate nocase in the column definition (the other options are binary (the default) and rtrim; see here). You can specify collate nocase when you create an index as well. For example:
create table Test
(
Text_Value text collate nocase
);
insert into Test values ('A');
insert into Test values ('b');
insert into Test values ('C');
create index Test_Text_Value_Index
on Test (Text_Value collate nocase);
Expressions involving Test.Text_Value should now be case insensitive. For example:
sqlite> select Text_Value from Test where Text_Value = 'B';
Text_Value
----------------
b
sqlite> select Text_Value from Test order by Text_Value;
Text_Value
----------------
A
b
C
sqlite> select Text_Value from Test order by Text_Value desc;
Text_Value
----------------
C
b
A
The optimiser can also potentially make use of the index for case-insensitive searching and matching on the column. You can check this using the explain SQL command, e.g.:
sqlite> explain select Text_Value from Test where Text_Value = 'b';
addr opcode p1 p2 p3
---------------- -------------- ---------- ---------- ---------------------------------
0 Goto 0 16
1 Integer 0 0
2 OpenRead 1 3 keyinfo(1,NOCASE)
3 SetNumColumns 1 2
4 String8 0 0 b
5 IsNull -1 14
6 MakeRecord 1 0 a
7 MemStore 0 0
8 MoveGe 1 14
9 MemLoad 0 0
10 IdxGE 1 14 +
11 Column 1 0
12 Callback 1 0
13 Next 1 9
14 Close 1 0
15 Halt 0 0
16 Transaction 0 0
17 VerifyCookie 0 4
18 Goto 0 1
19 Noop 0 0
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
You can do it like this:
SELECT * FROM ... WHERE name LIKE 'someone'
(It's not the solution, but in some cases is very convenient)
"The LIKE operator does a pattern
matching comparison. The operand to
the right contains the pattern, the
left hand operand contains the string
to match against the pattern. A
percent symbol ("%") in the pattern
matches any sequence of zero or more
characters in the string. An
underscore ("_") in the pattern
matches any single character in the
string. Any other character matches
itself or its lower/upper case
equivalent (i.e. case-insensitive
matching). (A bug: SQLite only
understands upper/lower case for ASCII
characters. The LIKE operator is case
sensitive for unicode characters that
are beyond the ASCII range. For
example, the expression 'a' LIKE 'A'
is TRUE but 'æ' LIKE 'Æ' is FALSE.)."
This is not specific to sqlite but you can just do
SELECT * FROM ... WHERE UPPER(name) = UPPER('someone')
Another option is to create your own custom collation. You can then set that collation on the column or add it to your select clauses. It will be used for ordering and comparisons.
This can be used to make 'VOILA' LIKE 'voilà'.
http://www.sqlite.org/capi3ref.html#sqlite3_create_collation
The collating function must return an integer that is negative, zero, or positive if the first string is less than, equal to, or greater than the second, respectively.
Another option that may or may not make sense in your case, is to actually have a separate column with pre-lowerscored values of your existing column. This can be populated using the SQLite function LOWER(), and you can then perform matching on this column instead.
Obviously, it adds redundancy and a potential for inconsistency, but if your data is static it might be a suitable option.
Its working for me Perfectly.
SELECT NAME FROM TABLE_NAME WHERE NAME = 'test Name' COLLATE NOCASE
If the column is of type char then you need to append the value you are querying with spaces, please refer to this question here . This in addition to using COLLATE NOCASE or one of the other solutions (upper(), etc).
use like this
"select * from $pwsXDataHistory where type = '$type' COLLATE NOCASE and $t_uStatus != '$DELETE' order by $t_name COLLATE NOCASE asc ");
Simply, you can use COLLATE NOCASE in your SELECT query:
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
you can use the like query for comparing the respective string with table vales.
select column name from table_name where column name like 'respective comparing value';
(Feel free to improve the question title if you can think of something better.)
Question: Consider the following SQLite query:
SELECT COUNT(*)
FROM (SELECT 1 AS value UNION SELECT 2 AS value)
WHERE value <= ?
When I use 1 as the parameter, I expect the query to yield 1, yet it yields 2. Why does this happen?
Additional information:
This is a minimal working example to reproduce the issue (Android):
Cursor c = db.rawQuery(
"SELECT COUNT(*) " +
" FROM (SELECT 1 AS value UNION SELECT 2 AS value) " +
" WHERE value <= ? ",
new String[] {String.valueOf(1)});
c.moveToFirst();
Log.i("", "Result: " + String.valueOf(c.getInt(0)));
It might have to do with the fact that the parameter is passed as a string, but, alas, there is no other way to pass parameters to the SQLite API, so I guess I'm not doing anything "wrong" here and it's SQLite's job to convert the value appropriately. I've also observed the following when using a non-parameterized version of the query (this might or might not be relevant for the issue):
SELECT COUNT(*)
FROM (SELECT 1 AS value UNION SELECT 2 AS value)
WHERE value <= 1 -- yields 1
SELECT COUNT(*)
FROM (SELECT 1 AS value UNION SELECT 2 AS value)
WHERE value <= '1' -- yields 2
It's said in the rawQuery documentation:
[...] You may include ?s in where clause in the query, which will be replaced by the values from selectionArgs. The values will be bound as Strings.
And, quoting the SQLite doc:
The results of a comparison depend on the storage classes of the
operands, according to the following rules [...]
An INTEGER or REAL value is less than any TEXT or BLOB value.
As both 1 and 2 are integers, they're both less than '1' (TEXT value). That's why this statement:
SELECT 2 <= '1'
... returns 1 in SQLite.
You should probably use ...
WHERE value <= CAST('1' AS INTEGER)
... instead. Or you can use the fact that all mathematical operators cast both operands to the NUMERIC storage class with WHERE value <= + ?, but this is less clean, imo.
Note that in this query:
SELECT * FROM myTable WHERE _id < ?
... the value of ? will get its affinity adjusted to the affinity of _id column - hence they will be compared as numbers, if _id is NUMERIC.
I have a table containing a BLOB column (it's just 16 bytes). I want to run a query of the form SELECT * FROM myTable WHERE blobColumn = ? and bind a byte array to that column. Ideally I would be able to say
myDatabase.rawQuery("SELECT * FROM myTable WHERE blobColumn = ?", myByteArray)
or some variant thereof, but the rawQuery function only supports String arguments - although looking though the Android sources, it seems that the private methods do include bindBlob(int, byte[]).
I can, of course, just run the query SELECT * FROM myTable WHERE blobColumn = x'CAFE1234CAFE1234CAFE1234CAFE1234', but is there a way to do it that doesn't require converting the blob to a string?
Try this as your argument to your ? query:
new String [] { String.valueOf(mByteArray) }
I don't believe that you can compare the contents of a Blob field without first converting it. Could you create an additional column and load it with some type of key that could be unique and descriptive of it's associated Blob data?