Can anyone help me the below query is working fine in DB Browser but not work with the Room database. Here are the table and query:
Table Transaction:
id
amount
is_credit
Query:
SELECT *
FROM
(SELECT
id, amount,
SUM(CASE WHEN is_credit = 1 THEN amount ELSE -amount END) OVER (ORDER BY id) AS balance
FROM `Transaction`)
ORDER BY
id DESC;
I have tried this query with SimpleSQLiteQuery but I'm getting error :
E/SQLiteLog: (1) near "(": syntax error
If your version of SQLite is lower than 3.25.0 then you can't use window functions like SUM().
Instead you can do it with a correlated subquery:
SELECT t.id,
t.amount,
(SELECT SUM(CASE WHEN tt.is_credit = 1 THEN 1 ELSE -1 END * tt.amount) FROM `Transaction` tt WHERE tt.id <= t.id) AS balance
FROM `Transaction` t
ORDER BY t.id DESC;
Or a self join:
SELECT t.id,
t.amount,
SUM(CASE WHEN tt.is_credit = 1 THEN 1 ELSE -1 END * tt.amount) AS balance
FROM `Transaction` t INNER JOIN `Transaction` tt
ON tt.id <= t.id
GROUP BY t.id
ORDER BY t.id DESC;
See a simplified demo.
You are trying to use SQLite Windows functions i.e OVER the version of SQLite on Android Devices is typically some way behind. You'd need at least API 30 (Android R) for SQLite version 3.28.0 (when Windows functions were introduced). Obviously that would place limitations on the App's install base.
You may wish to see Version of SQLite used in Android?
Related
I want retrieve the last 10 rows for each chat_id match in a table.
This works perfect:
SELECT *
FROM
(SELECT a.*,
row_number()
OVER (PARTITION BY a.chat_id
ORDER BY a.timestamp DESC ) AS row
FROM messages a ) AS foo
WHERE row <= 10
But when i put this code on my React Native app, it throws and error, and its because this its only supported in SQLite 3.25.0 and above.
https://developer.android.com/reference/android/database/sqlite/package-summary.html
Is there another way to do this? I'm trying to avoid multiple queries to SQL.
One option is to use a correlated subquery to count how many records have the same chat_id and a greater timestamp than the current row, and use the result for filtering:
select m.*
from messages m
where (
select count(*)
from messages m1
where m1.chat_id = m.chat_id and m1.timestamp > m.timestamp
) < 10
I have ids in my table, ids start from 1 to 20, I want a query, to find the first and last records in a given table but I want the result by some condition.
For example: if I have the record
1,2,3,4,5,9,10,11,12,13, 19,20
I need a result like 1-5, 9-13, 19-20 like this I need results
This is the island part of the classic gaps and islands problem (With the gaps part being finding the missing values in between each island). If you search for that term, you'll find a ton of material about how to calculate them.
One approach (Requires Sqlite 3.25 or newer for window function support):
sqlite> CREATE TABLE ex(id INTEGER PRIMARY KEY);
sqlite> INSERT INTO ex VALUES (1),(2),(3),(4),(5),(9),(10),(11),(12),(13),(19),(20);
sqlite> WITH cte AS (SELECT id, id - row_number() OVER (ORDER BY id) AS grp FROM ex)
...> SELECT min(id) AS rangestart, max(id) AS rangeend FROM cte GROUP BY grp;
rangestart rangeend
---------- ----------
1 5
9 13
19 20
SQL Query to find first record in your table:
SELECT * FROM <table_name> ORDER BY <column_name> ASC LIMIT 1
SQL Query to find last record in your table:
SELECT * FROM <table_name> ORDER BY <column_name> DESC LIMIT 1
For example: if I have the record 1,2,3,4,5,9,10,11,12,13, 19,20
I need a result like 1-5, 9-13, 19-20 like this I need results
If you need result like you have mentioned, then you can set LIMIT in your query to get how many records you can have in that query.
QUERY:
SELECT * FROM <table_name> LIMIT <any_number>
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 am trying to create a static list of timestamps so that i can join them agains another table to create chart data. So far I have a query in this format SELECT * FROM (VALUES('a'),('b'),('c'),('d')) AS tbl ,which is working in sqlitestudio but not in android 4.4. When I run the query in the phone I get the error
android.database.sqlite.SQLiteException: near "VALUES": syntax error (code 1): , while compiling: SELECT * ...
I have also tried wrapping the values term inside another select like this SELECT * FROM (SELECT * FROM (VALUES('a'),('b'),('c'),('d'))) AS tbl but I still get the same error.
The full query now looks like this
SELECT * FROM (select * from ( VALUES (1458111312025),
(1455667200000),
(1455753600000),
(1455840000000),
(1455926400000),
(1456012800000),
(1456099200000),
(1456185600000),
(1456272000000),
(1456358400000),
(1456444800000),
(1456531200000),
(1456617600000),
(1456704000000),
(1456790400000),
(1456876800000),
(1456963200000),
(1457049600000),
(1457136000000),
(1457222400000),
(1457308800000),
(1457395200000),
(1457481600000),
(1457568000000),
(1457654400000),
(1457740800000),
(1457827200000),
(1457913600000),
(1458000000000),
(1458086400000))) i LEFT JOIN (
SELECT (osysdate- (osysdate % 86400000) ) interval, SUM(field004) totalval FROM onlineactivities WHERE field003 !=300000 and osysdate> 1455605711999 GROUP BY interval )
onl ON i.'' = onl.interval;;
Note that this works in sqlitestudio with sqlite version 3.8.10 but not in android kitkat (not sure about the sqlite version in it) What could be the problem?
Also please check out this question which is what I am trying to do but with sqlite and this answer
The VALUES syntax is available since SQLite 3.8.3, which is not available in every Android version.
To be compatible with earlier SQLite versions, you have to use a compound query:
SELECT 1458111312025 UNION ALL
SELECT 1455667200000 UNION ALL
...
Alternatively, put all the values into a temporary table.
I'm developing an Android application. I have a database table and I want to request two or more different SELECT expression with different WHERE condition and the same LIMIT for each expression. My query is like:
(SELECT * FROM questions WHERE level=1 LIMIT 5)
UNION
(SELECT * FROM questions WHERE level=2 LIMIT 5)
When running application this query causes error that says:
near "UNION": syntax error: while compiling <here is my query>
When I omit the LIMIT it works well but LIMIT and ORDER BY don't work with UNION this way. My query is correct for MySQL according their documentation. But I couldn't find any SQLite documentation for my problem. So how should I query SQLite table for my needs?
Try
SELECT * FROM
(
SELECT * FROM
(SELECT * FROM questions WHERE level=1 LIMIT 5)
UNION
SELECT * FROM
(SELECT * FROM questions WHERE level=2 LIMIT 5)
)