Android Content Provider how to query with multiple selectionArg - android

I have table like below:
Students:
id | student_name
------------------
1 | max
2 | alex
3 | james
I want to query only students which have id 1 and 3.
getContentResolver().query(StudentContentProvider.CONTENT_URI2, projection,"id=?",selectionArg,null);
what I have to write in selectionArg so i only get students with id 1 and 3 ?

have you tried
getContentResolver().query(StudentContentProvider.CONTENT_URI2, projection,"id=1 or id=3",null,null);
or if you use placeholders "?" selectionArg must contain values "1" and "3"
getContentResolver().query(StudentContentProvider.CONTENT_URI2, projection,"id=? or id=?",selectionArg,null);

The answer i found is to add id in (?,?) for "selection" and give "selectionArgs[]" to query. ? signs replaced with elements inside "selectionArgs[]". You have to add ? for each element so i did this:
String selection1 = DatabaseOpenHelper.COLUMN_ID + " in (";
for (int i = 0; i < selectionArgs1.length; i++) {
selection1 += "?, ";}
selection1 = selection1.substring(0, selection1.length() - 2) + ")";
getContentResolver().query(StudentContentProvider.CONTENT_URI1, projection1, selection1, selectionArgs1, null);

Related

sqlite android select sum

my table look like this:
Client_Code Oder_ID NoOrd Weight
850458 5 1 12
850458 5 2 12
850458 6 1 5
i want to sum the Weight, but unique par Oder_ID.
so the resultat that i want is 17 = 12 + 5
not 29
how can i do that ?
my code like this;
public int GetPoids()
{
String SQL_syntax = "SELECT SUM("+ DBHelper.KEY_Poids +") as SumPoids FROM " + DBHelper.tableName + " GROUP BY " + DBHelper.KEY_CodeClient +","+DBHelper.KEY_NoOrdre ;
Cursor c = database.rawQuery(SQL_syntax, null);
if (c != null)
c.moveToFirst();
int Poids = c.getInt(0);
c.close();
return Poids;
}
Give a try, First you need to get unique OrderIds then take only one record of that OrderId with one more condition NoOrd=1 (it must have atleast NoOrd=1 in each record)
select sum(Weight) from Table_Name where Order_ID in (select distinct Order_ID from Table_Name) and NoOrd=1
Sorry if it doesn't help you, actually I tried on a online tool due to lack of your database structure.

Select only last inserted row per parent_id

Here is my sqlite table:
_ID | DATE_INSERTED | LATITUDE | LONGITUDE | TRACKER_ID | DATA
I need to get a Cursor with the last inserted row (by DATE_INSERTED) per TRACKER_ID, where LATITUDE and LONGITUDE are not equal to "0".
I'm doing it in a CursorLoader, this is where I could get:
public static CursorLoader getLoaderForLastMessages(Context context) {
String sel = MessageTable.LONGITUDE + " !=? and " + MessageTable.LATITUDE + " !=?";
String[] selArgs = {"0", "0"};
return new CursorLoader(context, GpsProvider.MESSAGE_CONTENT_URI, null, sel, selArgs, null);
}
I don't know how to select only the last row per TRACKER_ID. I guess DISTINCT and GROUP BY are good words, but I don't know how to use them correctly.
A raw SQLITE query is a good answer too, I'll adapt it to my code.
EDIT:
To clarify I need a Cursor like this:
_ID | DATE_INSERTED | LATITUDE | LONGITUDE | TRACKER_ID | DATA
3 | 23424123 | 13 | 43 | 1 | data
6 | 23563344 | 25 | 56 | 2 | data
19 | 56573473 | 37 | 12 | 3 | data
43 | 23635743 | 82 | 99 | 4 | data
You can query the Table for the last inserted RowID:
//Get the last inserted unique primary id (_id) of your table.
public int getPrimaryId() {
final String MY_QUERY = "SELECT MAX(_id) FROM " + DATABASE_TABLE0;
Cursor cur = mDb.rawQuery(MY_QUERY, null);
cur.moveToFirst();
int ID = cur.getInt(0);
cur.close();
return ID;
}
You can use this ID to specify in a query and load the results in your cursor.
Try this:
String selectQuery = "SELECT * FROM " + <TABLE_NAME> + " WHERE TRACKER_ID = \"" + <trackID> + "\" AND LATITUDE != '0' AND LONGITUDE != '0' AND DATE_INSERTED = \"" + <date>" ;
Cursor cursor = sqliteDatabase.rawQuery(selectQuery, null);
if(cursor.moveToLast()){
//Get the value here using cursor.getString(<column number>)
}
May be a Select Query like:
SELECT A._ID , A.DATE_INSERTED , A.LATITUDE , A.LONGITUDE , A.TRACKER_ID , A.DATA
FROM MY_TABLE A
JOIN
(
SELECT TRACKER_ID, MAX(DATE_INSERTED) MAX_DATE_INSERTED FROM MY_TABLE
WHERE LATITUDE <> '0' AND LONGITUDE <> '0'
) B
ON A.TRACKER_ID = B.TRACKER_ID
AND A.DATE_INSERTED = B.MAX_DATE_INSERTED

android sqlite select avg multiple columns

I have a problem with a query of sqlite. I want to do is the average of two columns and place the result in a new column. example:
id | max_ma | max_ta | avg_max (new column)
1 | 100 | 102 | 101 ==> (100+102)/2
2 | 100 | null | 100 ==> (100+0)/1 INGNORE NULL
wrong code:
public Cursor list() {
String lista_ge = "SELECT *, AVG(tr_max_m + tr_max_t) AS media_max FROM bdt_registro ORDER BY tr_fecha DESC, _id DESC";
return db.rawQuery(lista_ge, null);
}
or
public Cursor list() {
String lista_ge = "SELECT *, ((tr_max_m + tr_max_t)/COUNT(*)) AS media_max FROM bdt_registro ORDER BY tr_fecha DESC, _id DESC";
return db.rawQuery(lista_ge, null);
}
Thanks for your interest
Use the COALESCE function:
SELECT *,
(COALESCE(tr_max_m, tr_max_t, 0) + COALESCE(tr_max_t, tr_max_m, 0)) / 2 AS media_max
FROM
bdt_registro ORDER BY tr_fecha DESC, _id DESC
If both are non_NULL you get: (tr_max_t + tr_max_m) / 2
If tr_max_m is NULL you get: (tr_max_t + tr_max_t) / 2 = tr_max_t
If tr_max_t is NULL you get: (tr_max_m + tr_max_m) / 2 = tr_max_m
If both are NULL you get: (0 + 0) / 2 = 0
Probably the best approach will be to use a lot of cases:
SELECT max_ma, max_ta,
CASE WHEN max_ma IS NULL THEN
CASE WHEN max_ta IS NULL THEN 0
ELSE max_ta END
ELSE
CASE WHEN max_ta IS NULL THEN max_ma
ELSE (max_ma + max_ta) / 2 END
END avg_max
FROM user_address
Fiddle here.
By the way, I noticed you were trying to use AVG. If you're wondering how you could have used that function then this will give you an idea. It won't be faster than the previous approach because it adds more calculation, though:
SELECT id,
max(CASE WHEN kind = 1 THEN aMax END) max_ma,
max(CASE WHEN kind = 2 THEN aMax END) max_ta,
avg(aMax) aMax
FROM (
SELECT id, max_ma aMax, 1 kind FROM user_address
UNION ALL
SELECT id, max_ta, 2 FROM user_address
) s
GROUP BY id
Another solution based on function IFNULL and...
... "un-aggregated" aggregated function COUNT:
SELECT *,
(IFNULL(max_ma, 0)+IFNULL(max_ta, 0))/(COUNT(max_ma)+COUNT(max_ta)) AS avg_max
FROM bdt_registro
GROUP BY id;
... CASE:
SELECT *,
(IFNULL(max_ma, 0)+IFNULL(max_ta, 0)) / (CASE WHEN max_ma IS NULL THEN 0 ELSE 1 END + CASE WHEN max_ta IS NULL THEN 0 ELSE 1 END) AS avg_max
FROM bdt_registro;
ยป SQL Fiddle

update 5 successive row with 5 data in a sqlite database

I have two table(dic,learnDataTable) in a sqlite database in a android project.In learDataTable there are 5 rows only. My aim is to fetch 5 random data from dic table and update 5 rows of the learnDataTable with this fetched data.
N:B: the structure of dic and learnDataTable is similar and they have two field and these are word as string type and meaning as string type.
I tried like this.
// fetch 5 random data from dic table
String sql ="SELECT * FROM dic ORDER BY RANDOM() LIMIT 5" ;
Cursor mCur = mDb.rawQuery(sql, null);
if (mCur!=null)
{
mCur.moveToNext();
}
//now update learnDataTable
for (int i = 0; i < mCur.getCount(); i++)
{
mCur.moveToPosition(i);
String word = mCur.getString(0).toString();
String meaning = mCur.getString(1).toString();
String sql2 ="update learnDataTable set english='"+word+"',bangla='"+meaning+"'";
mDb.execSQL(sql2);
}
But i know it just update all rows each time. My aim to update learnDataTable with 5 random data from dic table.
How can i do that???
Check this:
//Clears learnDataTable:
mDb.execSQL("DELETE FROM learnDataTable");
//Insert 5 random rows from dic:
mDb.execSQL("INSERT INTO learnDataTable (english, bangla) SELECT english ,bangla FROM dic ORDER BY RANDOM() LIMIT 5");
Fast and simple!
Select out the unique rowid out from your dic table as well, as it's needed in the update statement.
// fetch 5 random data from dic table
String sql = "SELECT rowid, english ,bangla "
+ "FROM dic ORDER BY RANDOM() LIMIT 5";
...
// now update learnDataTable
for (int i = 0; i < mCur.getCount(); i++) {
mCur.moveToPosition(i);
int id = mCur.getInt(0);
String word = mCur.getString(1);
String meaning = mCur.getString(2);
String sql2 = "update learnDataTable set english='" + word
+ "',bangla='" + meaning + "'" + " WHERE rowid = " + id;
mDb.execSQL(sql2);
}

What is the best way to do SELECT in SQLite with equals subqueries

I do big query with few subqueries and unions:
public Cursor getCursor(int outlayType, long carId){
String selection;
String[] selectionArgs;
if(outlayType>0){
selection = "car_id=? and type=?";
selectionArgs = new String[]{
Long.toString(carId),Integer.toString(outlayType),
Long.toString(carId),Integer.toString(outlayType),
Long.toString(carId),Integer.toString(outlayType)};
}else{
selection = "car_id=?";
selectionArgs = new String[]{Long.toString(carId), Long.toString(carId), Long.toString(carId)};
}
String sql = "select (select count(*)+1 from outlays b where a.date < b.date and "+selection+") as countNum," +
" id as _id, id, type, note, sum, date," +
" odometer, unread, future, input_type, 0 as row_type " +
" from outlays a where "+ selection +" " +
" union " +
" select 0, 0, 0, 0, '', sum(sum), max(date)+2," +
" 0, 0, 0, '', 1 as row_type" +
" from outlays where "+ selection +" group by strftime('%Y-%m', date/1000, 'unixepoch')" +
" order by 7 DESC";
return sqdb.rawQuery(sql, selectionArgs);
}
It works perfect, but ...
You can see: few times I use same WHERE conditions. And this is not the end. The query will grow. And this conditions will be use again and again.
I want to use temp table like this:
public Cursor getCursor(int outlayType, long carId){
String selection;
String[] selectionArgs;
if(outlayType>0){
selection = "car_id=? and type=?";
selectionArgs = new String[]{Long.toString(carId),Integer.toString(outlayType)};
}else{
selection = "car_id=?";
selectionArgs = new String[]{Long.toString(carId)};
}
sqdb.execSQL("drop table if exists sub");
sqdb.execSQL("create temp table sub " +
"as select * from outlays where "+selection, selectionArgs);
String sql = "select (select count(*)+1 from sub b where a.date < b.date) as countNum," +
" id as _id, id, type, note, sum, date," +
" odometer, unread, future, input_type, 0 as row_type " +
" from sub a " +
" union " +
" select 0, 0, 0, 0, '', sum(sum), max(date)+2," +
" 0, 0, 0, '', 1 as row_type" +
" from sub group by strftime('%Y-%m', date/1000, 'unixepoch')" +
" " +
" order by 7 DESC";
return sqdb.rawQuery(sql, null);
}
It looks better (for me), but when I call Cursor.notifyDataSetChanged - it works wrong. Because the recreation of temp table is not called.
How can I do one subquery or one temp table in the same query for Cursor?
I not sure what your ultimate goal is, but I was able to convert your first query into a correlated query. That is where the subselect gets if values for a column from the main query. The key is that the main query column MUST always be on the right side of the comparison operator in the subselect, so I reversed the dates and switch the comparison operator.
Using the following data as input:
1 1 1 note 1 1 20130601 6100 1 1 0 201306
2 2 2 note 2 2 20130701 72013 0 1 0 201307
3 3 3 note 3 3 20130715 4201 1 1 a 0 201307
4 3 3 note 4 4 20130318 68010 1 1 0 201303
5 1 1 note 5 5 20130615 37077 1 1 0 201306
I couldn't replicate the strftime with the tool is was using so I added the last column ym, which I believe is equivalent to your result of strftime for your group by.
Here's the SQL i came up with:
select (select count(*)+1 from outlays b where b.date1 > a.date1 and b.car_id=a.car_id) as countNum,
id as _id, a.id, a.type, a.note, a.sum1, a.date1, a.odometer, a.unread, a.future, a.input_type, 0 as row_type, ym
from outlays a where car_id= 1
union all
select 0, 0, 0, 0, '', sum(sum1), max(date1)+2, 0, 0, 0, ' ', 1 as row_type, ym from outlays group by ym order by 7 DESC;
There are the data results:
#| |.|.|.|. |.|. |. |.|.|.|.|.
-+-+-+-+-+------+-+--------+-----+-+-+-+-+------
1|0|0|0|0| |5|20130717|0 |0|0| |1|201307
2|0|0|0|0| |6|20130617|0 |0|0| |1|201306
3|1|5|5|1|note 5|5|20130615|37077|1|1| |0|201306
4|2|1|1|1|note 1|1|20130601|6100 |1|1| |0|201306
5|0|0|0|0| |4|20130320|0 |0|0| |1|201303
Note in this particular case until I really know the goal, either UNION or UNION ALL can be used.
Some things I noted and changed a few in the above:
There probably isn't a column name issue here 'id as _id and id' with the exception that you are almost being reduntant, in the future just use _id. Anyone maintaining the code will then understand it a bit quicker. Nice way to get around the _id requirement by android methods.
There is also an issue probably with a column names of 'sum', and 'date' since it is also a sql function or might be, or a reserved word in some language and if not, I would just avoid out of good database design.
FYI: Not that this one matters at all, but type isn't really descriptive, column names should be descriptive, so type should be type_ofwhat, but that only if you want to follow good database design.
In addition, since I didn't know your intent, I wasn't sure there were other columns that you would want to group by. From my experience, typically there are.
The two queries might be able to be one, again I'd need to know what the real intent is for the result and all columns therein.
Hope this helps.

Categories

Resources