Android: ViewBinder & SimpleCursorAdapter SQL woes - android

I am struggling to get more complicated queries to work with SimpleCursorAdapter and ViewBinder with a ListView. When I was just returning all entries in my table, that was no problem. However, I want to return a list of artist names from my tables in order of name. The big problem concerns the "rowid _id" field which SimplerCursorAdapter/ViewBinder expects.
My code worked fine when I had queries of the form SELECT rowid _id, Artist.NAME etc, but I want to use the DISTINCT keyword to return the unique set if artist names. I can't put "rowid _id" before "DISTINCT Artist.Name" and I can't put it after. What is the solution for this?
The query I want (A) is (shown without the "rowid _id"):
String sQuery = String.format( "SELECT DISTINCT Artist.Name, Artist.ID FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID AND Tune.Type=%d AND Tune.SubType=%d ORDER BY Artist.Name", nType, nSubtype );
To clarify, this works:
Cursor c = db.rawQuery( "SELECT rowid _id, Name, Rating FROM Tune ORDER BY Name", null );
Whenever I put rowid _id back into query (A), I get "no such column rowid" exceptions:
String sQuery = String.format( "SELECT rowid _id, Artist.Name, Artist.ID FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID AND Tune.Type=%d AND Tune.SubType=%d ORDER BY Artist.Name", nType, nSubtype );
What am I doing wrong?
EDIT: I don't even understand what the "rowid _id" does anyway - my SQLite Manager (test tool) doesn't like it either when I have a query with a join. It only seems to work on a simple 1 table query.. So if thats the case.. how do I make this query work without it for SimpleCursorAdapter & ViewBinder?

The answer was to forget about using rowid and use my own Artist.ID field instead. This will work as long as I alias the field name to _id which SimpleCursorAdapter expects in column 0.
String sQuery = String.format( "SELECT DISTINCT Artist.ID _id, Artist.Name FROM Artist JOIN Tune ON Artist.ID=Tune.ArtistID AND Tune.Type=%d AND Tune.SubType=%d ORDER BY Artist.Name", nType, nSubtype );

Related

Content provider with multiple joins on same table

I'm working with a ListView that has a CursorAdapter and the query is done via LoaderManager to my ContentProvider. Everything seems to work fine, but when I try to do a multiple query with the same table I get a duplicated column error:
table rating:
CREATE TABLE rating ( _id INTEGER PRIMARY KEY, message TEXT NOT NULL,
from_user_id INTEGER NOT NULL, to_user_id INTEGER NOT NUL);
table users:
CREATE TABLE users ( _id INTEGER PRIMARY KEY, name TEXT NOT NULL,
avatar TEXT, GENDER TEXT);
QueryBuilder:
queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables(rating LEFT JOIN users ON
rating.from_user_id = users._id LEFT JOIN users
ON rating.to_user_id = users._id );
Is there any way to use an alias or any similar approach?
Yes, you can use the as keyword to set an alias for a table. Check out https://www.sqlite.org/syntax/join-clause.html and https://www.sqlite.org/syntax/table-or-subquery.html.
Your join clause would look like this:
rating LEFT JOIN users as from_users ON rating.from_user_id = from_users._id
LEFT JOIN users as to_users ON rating.to_user_id = to_users._id
Actually you only need to set an alias for one of both occurrences of users, but setting an alias for both makes it easier to read and understand.
Note that you also need to prefix all columns that come from the users table in your projection and all other parts of the query (e.g. where, order by).
So given that you're interested in the user names of both users (the rating user and the rated user), your projection would look like this:
new String[]{"from_users.name", "to_users.name"};

Displaying rows from different tables to one ListView in Android - without SQL JOIN

I'm super-novice at Android programming and have this project I'm stuck on.
I have a database of (conlang) dictionaries where each language is in its own table. The user searches these and the results will display in a ListView. Right now, I've got it working to search only one table.
I want it to be able to search all three tables and display the results in one ListView with rows from each of the tables. I'd like to indicate which table each row came from. The results would display something like:
From language
Lang Term : English term
Additional information
I've set up a CursorAdapter and have this currently working for one of the three tables.
...
Since the dictionaries came from different sources, they have different information. As an example:
One has the columns EngTerm, VLangTerm, FullDefinition
Another has EngTerm, RLangTerm, PartOfSpeech
And the other has EngTerm, GLangTerm, PartOfSpeech, and PronounciationGuide (possibly).
For example, table1 might contain results for "land," "landing gear" and "landscape" and table2 might contain "land," "landing" and "island" and table3 might contain "bland" and "homeland."
The user can search these tables right now only by the english term, and can select to match by full word or partial word.
Because of how they are structured, I'm guessing there is no way to do a JOIN query.
I don't know if this helps at all, but right now, I've got this method in my SQLiteOpenHelper class:
public Cursor searchDictionaryByEnglish
(boolean matchFullWordOnly, String searchTerm) {
String sql = "SELECT * FROM " + TABLE_VULCAN +
" WHERE " + COLUMN_ALL_ENG_TERM + " MATCH ?";
if (!matchFullWordOnly)
searchTerm = "*" + searchTerm + "*";
return mDataBase.rawQuery(sql, new String[]{searchTerm});
}
(It is an FTS3 table it's searching, thus the MATCH rather than LIKE.)
I hope I've made it clear what I'm trying to accomplish, but I'm not sure where to start. I've found some answers about MergeCursor but I don't know how to apply that because of the different number and names of columns.
Here's how to do a union if you don't have one of the columns in one of the tables, it will work if you're only searching through the common column, that all the tables have.
SELECT field1 ,
field2 ,
field3
FROM ( SELECT field1 ,
field2 ,
field3
FROM table1
UNION
SELECT field1 ,
field2 ,
field3
FROM table2
UNION
SELECT field1 ,
field2 ,
NULL AS field3
FROM table3
) tbl
WHERE tbl.field1 LIKE '%search_string%'
Note the NULL AS field3 in the last UNION.
Create a Adapter that does accept the fields you require to display.

Android Sqlite subquery does not return any value

I am using the following query to get the list of item
Query="Select * from Item_List where idSubcategory = (Select _id from SubCategory_List where Name = ?)";
c = db.rawQuery(Query, new String[] { Search });
But it is returning no result.
I ran this query on the database which I pulled from the device as well as emulator. There I am getting proper result, But when I run it on device no data is returned.
Can you try a different way? Use execSQL() as explained in this link. It is exactly the same problem.
EDIT
Unfortunately i didn't notice that execSQL() return no data (the work day is ending, finally!). The only solution i have is to do a first query and the result of this one will be the parameter of second query.
EDIT 2
Try to add "IN" to your query, like this:
Query = "Select * from Item_List where idSubcategory in (Select _id from SubCategory_List where Name = ?)"

How do I join two SQLite tables with the Android API?

I like to use the query method instead of rawQuery because it is more elegant for me, but it seems that the method can receive only one table as an input parameter.
Is there a solution for many tables?
I dont think there's any other method which can offer you this flexibility. Thats why the API comes with the method rawQuery(). Use sql query using UNION to join data from two tables.
for example:
String query = "SELECT Id, Name FROM Finance " +
"UNION ALL " +
"SELECT Id, Name FROM Marketing";
Cursor c = db.rawQuery(query, null);
Best will be just using rawquery, but if you must stick with query:
( please note, I have not tested this, but I imagine it will work )
You should be able to create a view ( http://sqlite.org/lang_createview.html ) and then use the view name in place of a table name.

rawQuery wild card `"_"` not working

I have been trying to use the character wild card "_" in sqlite where conditions and am close to "jumping off a high place" I have tried both rawQuery and query with a variety of hard and soft coded parameters. It seems to ignores the character wild card "_"and returns all rows or none at all.
The data held is in several columns representing a features of an oblect for example a column may represent the colours of an object
("red,orange,yellow,green,blue,indego,violet,black")
and a row's colour could be "01001000" meaning that it is orange and blue but not red, yellow etc. other columns contain single characters ie size contains s,m or l (mapping small, medium, large ) the database holds several columns of each type, the idea to have as compact a database as possible.
My first intention was to code by passing the 'where' of my select as a string to the rawQuery(myselect,null) where the myselect was compiled in the code in response to several features selected by the user.
ie
the mywhere string is compiled to return :-
colour1 like "_1__10__" and colour2 like "___1_01__" and size ="l"
and passed to the rawQuery
db.rawQuery("SELECT _id , name FROM widgets WHERE " + mywhere , null);
The statement below works fine using Firefox's SQLite Manager
SELECT _id , name FROM widgets WHERE colour1 like "_1__10_" and colour2 like "__1_01___" and size ="m"
In order to investigate I have cut the query down to one column in the where clause
myselect ="SELECT _id ,name,FROM widgets where colour1 like \"1_______\"";
cursor = db.rawQuery(myselect,null);
returns no rows
myselect ="SELECT _id ,name,FROM widgets where colour1 like \"%1_______%\"";
cursor = db.rawQuery(myselect,null);
returns rows but not all have a 1 at the first char ( I expected this )
myselect ="SELECT _id ,name, FROM widgets where colour1 like ?";
String[] whereArguments = { "1_______" };
cursor = db.rawQuery(myselect,whereArguments);
returns no rows
myselect ="SELECT _id ,name, FROM widgets where colour1 like ?";
String[] whereArguments = { "%1_______%" };
cursor = db.rawQuery(myselect,whereArguments);
returns rows but not all have a 1 at the first char
But I dont get any rows from
myselect ="SELECT _id ,name, FROM widgets where colour1 like ?";
String[] whereArguments = { "10000000" };
cursor = db.rawQuery(myselect,whereArguments);
and there are rows containing "10000000"
Does any one have any solutions? I have tried searching but it seems that rawQuery and query have questionable functionality in Android.
Not sure if this is your main source of problems, but the string delimiter in SQLite is the single quote character (') not the double quote one ("). See this, for example.

Categories

Resources