I have an sqlite database in android app and I want to search in (zan) table between 1-100 range in (id) column then withing that range find words similar in (eng) column, but it does not return anything and it does not give error either, thanks.
"Select * from zan where id (between 1 and 100) and eng like '"+smilarkeyword+"&'"
Should be id between and the wildchar for like is % (or _)
"Select * from zan
where id between 1 and 100
and eng like '%"+smilarkeyword+"%'"
where % stands for 0 or more characters and _ stands for exactly one character
Related
In Android SQLite i got tabel like this
domainObjectId: String // like '9876543210'
name: String
description: String
I want to use FTS on this to search without worrying about diacritical marks, how ever i want to let user select also by typing part of object ID(ex. last 4 char)
I got select like
`SELECT * FROM tabel LEFT JOIN tabel_fts on tabel_fts.domainObjectId = tabel.domainObjectId WHERE tabel_fts MATCH '3210*' OR tabel.domainObjectId LIKE '%3210%'
But in return i get error
unable to use function MATCH in the requested context (code 1 SQLITE_ERROR);
Is this possible to add additional condition to select with MATCH?
Try to remove "MATCH" into separate "SELECT":
`SELECT * FROM tabel LEFT JOIN (select * from tabel_fts WHERE tabel_fts.domainObjectId MATCH '3210*') as tabel_fts WHERE tabel.domainObjectId LIKE '%3210%' OR table_fts.ID IS NOT NULL
By the way:
In your "WHERE tabel_fts" it seemed you've missed a column name
There is no "ON" condition in tables JOINm just "WHERE". That's OK? May be it would be better to use UNION?
I need get the total SUM for each rows in my query, but I don't want go twice in the table.
I tried do this:
SELECT id, value, SUM(value) as total FROM product
But my result was this:
id value total
3 30 60
If I do the bellow query I get my wanted result, but I need go twice in the table:
SELECT id, value, (SELECT SUM(value) FROM product) as total FROM product
Or if I use 'WITH' clause, but this is not supported before Android 5:
WITH data AS (SELECT id, value FROM product)
SELECT id, value, (SELECT SUM(value) FROM data) as total FROM data
Wanted result:
id value total
1 10 60
2 20 60
3 30 60
Thank you!
It's not possible using your SQLite version. You'll have to use two selects.
Basically you have to use a subquery.
However, perhaps you may be less concerned about the 2nd table as I believe that the Query Planner will determine that it only needs to calculate the sum once and does away with the need for a variable as it stores the value in cache.
I believe that the results of using EXPLAIN QUERY PLAN your_query shows this. i.e. using
EXPLAIN QUERY PLAN SELECT id, value, (SELECT sum(value) FROM products) AS total FROM products;
results in :-
This being explained as (see bolded statements) :-
1.3. Subqueries
In all the examples above, the first column (column "selectid") is
always set to 0. If a query contains sub-selects, either as part of
the FROM clause or as part of SQL expressions, then the output of
EXPLAIN QUERY PLAN also includes a report for each sub-select. Each
sub-select is assigned a distinct, non-zero "selectid" value. The
top-level SELECT statement is always assigned the selectid value 0.
For example:
sqlite> EXPLAIN QUERY PLAN SELECT (SELECT b FROM t1 WHERE a=0), (SELECT a FROM t1 WHERE b=t2.c) FROM t2;
0|0|0|SCAN TABLE t2
0|0|0|EXECUTE SCALAR SUBQUERY 1
1|0|0|SEARCH TABLE t1 USING COVERING INDEX i2 (a=?)
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 2
2|0|0|SEARCH TABLE t1 USING INDEX i3 (b=?)
The example above contains a pair of scalar subqueries assigned
selectid values 1 and 2. As well as a SCAN record, there are also 2
"EXECUTE" records associated with the top level subquery (selectid 0),
indicating that subqueries 1 and 2 are executed by the top level query
in a scalar context. The CORRELATED qualifier present in the EXECUTE
record associated with scalar subquery 2 indicates that the query must
be run separately for each row visited by the top level query. Its
absence in the record associated with subquery 1 means that the
subquery is only run once and the result cached. In other words,
subquery 2 may be more performance critical, as it may be run many
times whereas subquery 1 is only ever run once.
Unless the flattening optimization is applied, if a subquery appears
in the FROM clause of a SELECT statement, SQLite executes the subquery
and stores the results in a temporary table. It then uses the contents
of the temporary table in place of the subquery to execute the parent
query. This is shown in the output of EXPLAIN QUERY PLAN by
substituting a "SCAN SUBQUERY" record for the "SCAN TABLE" record that
normally appears for each element in the FROM clause. For example:
sqlite> EXPLAIN QUERY PLAN SELECT count(*) FROM (SELECT max(b) AS x FROM t1 GROUP BY a) GROUP BY x;
1|0|0|SCAN TABLE t1 USING COVERING INDEX i2
0|0|0|SCAN SUBQUERY 1
0|0|0|USE TEMP B-TREE FOR GROUP BY
If the flattening optimization is used on a subquery in the FROM
clause of a SELECT statement, then the output of EXPLAIN QUERY PLAN
reflects this. For example, in the following there is no "SCAN
SUBQUERY" record even though there is a subquery in the FROM clause of
the top level SELECT. Instead, since the flattening optimization does
apply in this case, the EXPLAIN QUERY PLAN report shows that the top
level query is implemented using a nested loop join of tables t1 and
t2.
sqlite> EXPLAIN QUERY PLAN SELECT * FROM (SELECT * FROM t2 WHERE c=1), t1;
0|0|0|SEARCH TABLE t2 USING INDEX i4 (c=?)
0|1|1|SCAN TABLE t1
EXPLAIN QUERY PLAN
End Note
Perhaps of relevance is this statement :-
The best feature of SQL (in all its implementations, not just SQLite)
is that it is a declarative language, not a procedural language. When
programming in SQL you tell the system what you want to compute, not
how to compute it. The task of figuring out the how is delegated to
the query planner subsystem within the SQL database engine.
Query Planning
You may also find this of interest he SQLite Query Optimizer Overview noting that as of release 3.8.0 The Next-Generation Query Planner is utilised.
I have a database of two columns in sqlite for android
id (INT) | owner (VARCHAR)
1477 jack
1578 jill
: :
9277 hill
1)
i like to get a count of the following: -
(group by the 1000s range)
RANGE | COUNT
0-999 0
1000-1999 5
:
8999-9999 7
2)
I also like to get a count of the following: -
(group by 100s range)
RANGE | COUNT
X1XX 5
X2XX 6
:
X9XX 7
3) and also group by 10s range.
I'm stuck with how to do the group by
SELECT COUNT(*) FROM myTable
GROUP BY ??
any pointers is appreciated.
Integer division by integers in sqlite3 yields integers:
select id/1000 as range_id, count(*) as range_count from mytable group by range_id;
To group by 100 ids, simply change 1000 to 100
sqlite3 has a printf() function that might be useful in make a pretty column to describe the range if you need something prettier than the integer division of id by group size.
I'm seeing some weird behaviour on my FTS enabled SQLite database. I have a table named fingerprints that contains a column named scan. Entries of scan are long strings that look like this:
00:13:10:d5:69:88_-58;0c:85:25:68:b4:30_-75;0c:85:25:68:b4:34_-76;0c:85:25:68:b4:33_-76;0c:85:25:68:b4:31_-76;0c:85:25:68:b4:35_-76;00:23:eb:ad:f6:00_-87; etc
It represent MAC addresses and signal strengths. Now I want to do string matching on the table and try to match for instance a MAC address:
SELECT _id FROM fingerprints WHERE scan MATCH "00:13:10:d5:69:88";
This returns a lot of rows that do not have the specified string in it for some reason. Second thing I will try to match is
SELECT _id FROM fingerprints WHERE scan MATCH "00:13:10:d5:69:88_-58";
This returns the same rows has before and is completely wrong.
Does SQLite treats the : _ - characters in any special way?
Thanks
What you're seeing is the effect of the FTS tokenizing your data.
The full text search doesn't work on un-processed long strings, it splits your data (and your search terms) into words and indexes them individually. The default tokenizer uses all alphanumeric characters and all characters with a code point >128 for words, and uses the rest of the characters (for example, as you're seeing : _ -) as word boundaries.
In other words, your search for 00:13:10:d5:69:88 will search for rows containing the words 00 and 13 and 10 and d5 and 69 and 88 in any order.
You can verify this behavior;
sqlite> CREATE VIRTUAL TABLE simple USING fts3(tokenize=simple);
sqlite> INSERT INTO simple VALUES('00:13:10:d5:69:88');
sqlite> SELECT * FROM simple WHERE simple MATCH '69:10';
-> 00:13:10:d5:69:88
EDIT: Apparently SQLite is smarter than I originally gave it credit for, you can use phrase queries (scroll down about a page from the link destination) to look for word sequences, which would solve your problem. Phrase queries are specified by enclosing a space (or other word separator) separated sequence of terms in double quotes (").
sqlite> SELECT * FROM simple WHERE simple MATCH '"69:10"';
-> No match
sqlite> SELECT * FROM simple WHERE simple MATCH '"69 88"';
-> 00:13:10:d5:69:88
sqlite> SELECT * FROM simple WHERE simple MATCH '"69:88"';
-> 00:13:10:d5:69:88
I did a bit of research about sql escape characters and count statements and didnt find a solution to my question. Even though I used stuff like:
SELECT * FROM table WHERE path LIKE '%/_%' ESCAPE '/';
I got a table where in a column there is paths so I want to select the items where I have certain number of slashes:
ID DIRECTORY
1 root/A
2 root/B
3 root/A/1/2
4 root/B/1/2
5 root/A/1
6 root/B/2
so, how do I select for example the elements that have only 2 slashes??
Edit 1: This is to be done in Android SQL-Lite Database
You can use a regular expression:
SELECT * FROM table WHERE path REGEXP '^([^/]*)/([^/]+)/([^/]*)$';
The above expression looks specifically for an optional group of characters not containing /, followed by /, followed by another group without /, followed by /, and optionally another set of characters before the end of the string.
So:
/Bxx92/2 -- match
5 root/A/1 -- match
6 root/Bxx92/2 -- match
6 root/Bxx92/2 -- match
7 root/Bxx92/ -- match
6 root/2 -- NO match
If there MUST be something before the first and after the last /, change the expression to '^([^/]+)/([^/]+)/([^/]+)$'
You can use this trick to count occurrences of a character in a string:
SELECT LENGTH('path') - LENGTH(REPLACE('path', '/', '')) AS `occurrences`
So you can achieve the goal with
SELECT id, path FROM
(SELECT id, path, LENGTH('path') - LENGTH(REPLACE('path', '/', '')) AS `occurrences`
FROM table) temp
WHERE occurrences = 2
However, I expect performance will be terrible. If you are going to query like that, consider adding a column with the path depth so that you can query directly with
SELECT id, path FROM table WHERE depth = 2