Sort in GreenDAO - android

Raw query:
SELECT * FROM SAVED_JOB2 S, JOB J WHERE J._id=S._id ORDER BY DATE_SAVED DESC
How can I achieve sort for column in JOIN table. I have tried:
QueryBuilder<Job> queryBuilder = daoSession.queryBuilder(Job.class);
queryBuilder.join(JobDao.Properties.Id, SavedJob2.class, SavedJob2Dao.Properties.Id);
List<Job> list = queryBuilder1.list();
This normal JOIN works perfect. But I need to sort for date_saved column in table SavedJob.
I tried to add this line:
queryBuilder.orderDesc(SavedJob2Dao.Properties.date_saved);
But this line returns this error:
Property 'date_saved' is not part of com.xxx.xxx.db.JobDao
Table JobDao:
id (PK)
title
description
requirements
allowance
type
status
Table SavedJobDao:
id (PK autoincrement)
j_id (FK to JabDao)
date_saved
status

You don't need to do any JOIN with greenDao. It works with objects, so in your savedJob you should have an object Job instead job_id.
So you can order by date_saved, but searching in savedJob only, you don't need either JOIN.
There are a lot of examples. And the official doc is awesome!.

Related

Get Wordpress posts with images link

I want to get wordpress posts with specific category and link of images.
As you know images links save to database in guid column, when post_type = attachment.
and ID of post and post_parent are the same.
Now I want to get posts and join guid column to same ID.
When I added Inner join to combine attachment and post, I got error!
Please help me, if you know the way that I can get post with specific category and images link of each post.
Here is my code:
SELECT
*
FROM
wp_posts p,
wp_postmeta m,
wp_terms t,
wp_term_taxonomy tt,
wp_term_relationships tr,
wp_terms t2,
wp_term_taxonomy tt2,
wp_term_relationships tr2
LEFT JOIN wp_posts AS p2
ON
p.ID = p2.post_parent
WHERE
p.post_type = 'post' AND p.post_status = 'publish'
AND p.ID = tr.object_id
AND t.term_id = tt.term_id
AND tr.term_taxonomy_id = tt.term_taxonomy_id
AND tt.taxonomy = 'category'
AND tt.term_id = t.term_id
AND t.name = 'Fashion'
GROUP BY
p.ID
ORDER BY
id
DESC
MySQL said:
#1054 - Unknown column 'p.ID' in 'on clause'
I suspect that the problem is due to mixing the old school comma syntax with the newer JOIN keyword.
Relevant excerpt from MySQL Reference Manual:
INNER JOIN and , (comma) are semantically equivalent in the absence of a join condition: both produce a Cartesian product between the specified tables (that is, each and every row in the first table is joined to each and every row in the second table).
However, the precedence of the comma operator is less than that of INNER JOIN, CROSS JOIN, LEFT JOIN, and so on. If you mix comma joins with the other join types when there is a join condition, an error of the form Unknown column 'col_name' in 'on clause' may occur. Information about dealing with this problem is given later in this section.
The easiest way to avoid this problem is to ditch the old school syntax for the join operation, use the JOIN keyword instead.
(It's great that the comma syntax is still valid, to provide backwards compatibility with existing SQL. But there's no good reason new development should use the comma syntax.)
Aside from that, there's a couple of big rock issues that stick out to me.
Seems like there's a lot of join conditions missing
Using * for the SELECT list in development can be useful shortcut, but we usually list the expressions we need to return, especially if we want to return id column from multiple tables, where we like to assign a column alias to avid duplicate columns names.
Relying on the non-standard extension to GROUP BY (when only_full_group_by is omitted from sql_mode to return values from "some" row in the collapsed group
Those all look like serious problems to me.
We can re-write the OP query to use JOIN keyword in place of comma syntax, and relocating conditions to the ON clause, this highlights what looks like missing join conditions:
SELECT *
FROM wp_posts p
JOIN wp_postmeta m
-- ON ???
JOIN wp_terms t
ON t.name = 'Fashion'
JOIN wp_term_taxonomy tt
ON tt.term_id = t.term_id
AND tt.taxonomy = 'category'
JOIN wp_term_relationships tr
ON tr.object_id = p.id
AND tr.term_taxonomy_id = tt.term_taxonomy_id
JOIN wp_terms t2
-- ON ???
JOIN wp_term_taxonomy tt2
-- ON ???
JOIN wp_term_relationships tr2
-- ON ??
LEFT
JOIN wp_posts AS p2
ON p2.post_parent = p.id
WHERE p.post_type = 'post'
AND p.post_status = 'publish'
GROUP
BY p.id
ORDER
BY p.id DESC
Where we are going to omit any join condition, and just match all rows to all other rows, then my preference is to include the (optional) CROSS keyword, as an aid the future reader, to signal that the omission of a join condition is by design, and not an oversight.

How can I get SUM values for each rows on SELECT without go twice in the table and without use 'WITH' clause?

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.

SQLite Fts select query

I am making a dictionary of over 20,000 words in it. So, to make it work faster when search data, i am using fts3 table to do it.
my select query:
Cursor c=db.rawQuery("Select * from data where Word MATCH '"+word+"*'", null);
Using this query, it will show all the word that contain 'word' , but what i want is to get only the word that contain the beginning of the searching word.
Mean that i want it work like this query:
Cursor c=db.rawQuery("Select * from data where Word like '"+word+"%'", null);
Ex: I have : apple, app, and, book, bad, cat, car.
when I type 'a': i want it to show only: apple, app, and
What can i solve with this?
table(_id primary key not null autoincrement, word text)
FTS table does not use the above attributes. It ignores data type. It does not auto increment columns other than the hidden rowid column. "_id" will not act as a primary key here. Please verify that you are implementing an FTS table
https://www.sqlite.org/fts3.html
a datatype name may be optionally specified for each column. This is
pure syntactic sugar, the supplied typenames are not used by FTS or
the SQLite core for any purpose. The same applies to any constraints
specified along with an FTS column name - they are parsed but not used
or recorded by the system in any way.
As for your original question, match "abc*" already searches from the beginning of the word. For instance match "man*" will not match "woman".
FTS supports searching for the beginning of a string with ^:
SELECT * FROM FtsTable WHERE Word MATCH '^word*'
However, the full-text search index is designed to find words inside larger texts.
If your Word column contains only a single word, your query is more efficient if you use LIKE 'a%' and rely on a normal index.
To allow an index to be used with LIKE, the table column must have TEXT affinity, and the index must be declared as COLLATE NOCASE (because LIKE is not case sensitive):
CREATE TABLE data (
...
Word TEXT,
...
);
CREATE INDEX data_Word_index ON data(Word COLLATE NOCASE);
If you were to use GLOB instead, the index would have to be case sensitive (the default).
You can use EXPLAIN QUERY PLAN to check whether the query uses the index:
sqlite> EXPLAIN QUERY PLAN SELECT * FROM data WHERE Word LIKE 'a%';
0|0|0|SEARCH TABLE data USING INDEX data_Word_index (Word>? AND Word<?)

How to Perform the following query using Greendao ?

I have 2 tables A and B.
Table A contains names and table B contains selected names.
Now I would like to perform the following query on these tables using greendao, Please let me know if it is possible and if it is not are there any alternatives (maybe a raw query).
select *
from A inner join B
on A.nameid = B.nameid
Also, Table A columns: id, nameid, name
and Table B columns: id, nameid, name, rating
I think this might help.
You can use the raw query as a fake join. And you get all you want in the Query object
Query query = ATableDao.queryBuilder().where(
new StringCondition("nameid IN " +
"(SELECT nameid FROM B_Table )").build();
Since "nameid" doesn't seems to be a unique identifier in your sample. I won't suggest to use Relations to solve this issue. If you are try to use Relations, you can find my previous answer here.
Try this:
List<ATableObj> listATableObj = ATableDao.queryRawCreate(", BTable BT
WHERE BT.nameid = T.nameid").list();
If you use greendao this works differntly:
Instead of your query you select rows from table a (or b) and if you need a field of b (or a) you call getB() (or getA()) to get the corresponding row of that table.
If you have rows in table a that have no match in table b and you have rows in table b that have no match in a and you onlly want to select everything that has matches uin both tables, you would have to do a raw query to filter the rows of a (or b).

SQL select specific fields in JOIN query

i'm writing an Android app and i've run into a bit of a roadblock involving databases. the way Android handles databases, i cannot refer to names in the result set by the usual 'tablename.colname' method, so this presents a huge issue when any tables in the database contain the same column name. what further complicates the issue, is that any table that is used by a ViewAdapter to display the data to the user (as in my application), must contain a field named "_id" as an autoincrement primary key int. therefore, some tables MUST have identical column names. however, to avoid this, it is possible to use an "AS" clause in a statement to rename the value in question. however, i'm using a rather long statement and i don't know how to limit the columns returned on a JOINed table. what i have is this, and it's completely illegal in android due to the 'tablename.colname' references. i actually added the table names in to make the statement more readable, but i can't use them:
SELECT call._id AS android_call_id,
call.phone,
call.time,
call.duration
call.duration_billed
call.pending
call.call_id
call.job_id
FROM call
LEFT OUTER JOIN phone ON call.phone_number=phone.phone
LEFT OUTER JOIN job ON job._id=call.job_id
WHERE call.pending=1 ORDER BY job._id
but what i need, is to rename the job._id to something else using an "AS" statement, same as with the 'call._id' field in the first part of the query. how do i achieve this renaming in a JOIN?
edit:
progress so far. i think i've worked out the syntax errors, but i get another runtime error "no such column 'job._id', which may be related to #Tom H. comment
edit 2:
turns out Tom was right, and i adjusted accordingly, but it doesn't work:
SELECT call._id AS android_call_id,
call.phone,
call.time,
call.duration,
call.duration_billed,
call.pending,
call.call_id,
call.job_id,
job._id AS android_job_id,
job.job_name,
job.job_number
FROM call
LEFT OUTER JOIN phone ON call.phone_number=phone.phone
LEFT OUTER JOIN job ON job._id=call.job_id
WHERE call.pending=1 ORDER BY job._id
error:
05-24 16:50:37.561: ERROR/Minutemaid - Service(7705): oops: ambiguous column name: call._id: , while compiling: SELECT call._id AS android_call_id,call.phone_number,call.time,call.duration,call.duration_billed,call.pending,call.call_id,call.job_id,job._id AS android_job_id,job.job_name,job.job_number FROM call LEFT OUTER JOIN phone ON call.phone_number=phone.phone LEFT OUTER JOIN call ON call.job_id=job._id WHERE call.pending=1 ORDER BY job._id
Can't you simply use AS to alias all of the tablename.columnname references to unique names in the result set?
You can simply create a VIEW that restricts columns selectable in a table and assigns another name to them.
You can try massaging the table names before you join them by using sub-queries with AS in the FROM clause. For example:
select c_phone, c_id, p_id
from (select id as c_id, phone as c_phone, phone_number as c_phone_number, ... from call) as c
left outer join (select id as p_id, phone as p_phone, ... ) as p
on c_phone_number = p_phone
...
If the limitation is just that you can't use table names to distinguish between columns but can use correlation names then simpler is:
select c.id, c.phone, p.id as "p_id" from ... call c join phone p

Categories

Resources