I have payment analysis app with the following simplified structure:
Payment
CREATE TABLE payments (
payment_Id TEXT NOT NULL,
payment_type INTEGER NOT NULL,
payment_name TEXT NOT NULL,
payment_category INTEGER NOT NULL,
payment_date TEXT NOT NULL,
payment_cost TEXT NOT NULL, PRIMARY KEY(payment_Id))
Category
CREATE TABLE categories (
category_Id INTEGER NOT NULL,
idRoot TEXT NOT NULL,
category_Name TEXT NOT NULL,
category_Type INTEGER NOT NULL, PRIMARY KEY(category_Id))
Foreign key: categories.category_Id = payment_category
Categories are structured in a tree hierarchy:
IdRoot
category_Id
Name
-
0
Unknown
0.
1
Expenses
0.1.
2
House
0.1.
3
Transport
0.1.
4
Travel
0.1.2.
5
Internet
0.1.2.
6
Groceries
0.1.2.
7
Water
0.1.3.
8
Car
0.1.3.
9
Public Transport
0.1.3.8.
10
Gasoline
0.1.3.8.
11
Tolls
...
...
....
Payments can be assigned to any category (except category_Id = 0).
I want to know if it is possible using just SQLite (compatible with Android is appreciated) to get all the children categories of a parent category and the sum of the payment_cost assign to every category in that level and its children.
Example: given category Transport(category_Id: 3), sqlite will return Car and Public Transport and their sums but the sum of Car will also include the payment_cost assign to Gasoline and Tolls something like this
Input: category_Id: 3
Data:
| payment_name | payment_cost| payment_category |
| ------------ | ---------- | ----------------- |
| Gas Station | 50,3 | 10 |
| Metro | 2,4 | 9 |
| Tool NY - Phil | 21 | 11 |
| Car cleaning | 11 | 8 |
Result
category_name
Total
Car
82,3 (50,3 + 21 + 11)
Public Transport
2,4
Thank you in advance for your time and knowledge
You can use like to get the matching roots:
select sum(payment_cost)
from payments p join
categories c
on p.payment_category = c.category_id cross join
categories c3
on c3.category_id = 3
where p.idroot like c3.idroot || '%'
Related
Imagine that i have a table like this in my room android database:
TABLE : PostalCode
id | cod | ext | city
-----------------------------------
1 | 2640 | 275 | Mafra
4 | 2695 | 650 | São João da Talha
...
When the user searches in editText something like this:
"São João"
"sAo joA da TaLH"
"sao talha"
"talh joa"
"joao talha"
I want to give him in the RecyclerView the second tuple
"4 | 2695 | 650 | São João da Talha"
I don't know how to make this query...
select * from PostalCode where ... ?
Fetch the data from room, apply a loop to the list you get, store city for each loop if it contains the given string by user like:
if(STR.contains("searched terms")) {
list.add(str);
}
Then show the list.
I have a database like
--------------------------------------------------
| _id| poi_id | poi_name |poi_address |
--------------------------------------------------
| 1 | 101 | sight_1 |sight_1_adr |
--------------------------------------------------
| 2 | 101 | sight_2 |sight_2_adr |
--------------------------------------------------
| 3 | 100 | sight_3 |sight_3_adr |
--------------------------------------------------
| 4 | 101 | sight_4 |sight_4_adr |
--------------------------------------------------
| 5 | 100 | sight_5 |sight_5_adr |
--------------------------------------------------
First of all , i want to create a listview and group my data by "poi_id".
I use the following query:
"SELECT* FROM poi_table GROUP BY poi_id"
I use a cursor with that query and i create the list view as:
entry.open();
Cursor cursor = entry.getData();
adapter = new CustomListAdapter(this.getActivity(), cursor);
setListAdapter(adapter);
My problem is that, in every list row, i would like to print also the poi_name of every poi_id.So iwould like to have something like:
-------------------------------
-101-
sight 1
sight 2
sight 4
-------------------------------
-100-
sight 3
sight 5
-------------------------------
etc
This is where i stack!
In my CustomCursorAdapter, i get the poi_id as:
String ID = cursor.getString(cursor
.getColumnIndex(db.POI_ID));
and then i use a second cursor to get the data like:
Cursor c2 = entry.getDatabyID(ID);
for (int i = 0; i < entry.fetchPlacesCountByID(ID); i++) {
c2.moveToPosition(i);
String name= c2
.getString(c2
.getColumnIndex(db.POINT_NAME));}
and i create dynamically a new textView and i set the string name there as text.
How can i fix it?That way doesnt crash but i get as many poi_names as i scroll down..
When I do this selcect:
SELECT tabuoj.id, tabuoj.tabuo, montritaj_tabuoj.id, montritaj_tabuoj.id_de_tabuo
FROM tabuoj LEFT JOIN montritaj_tabuoj
ON (tabuoj.id=montritaj_tabuoj.id_de_tabuo)
I get:
id | tabuo | id | id_de_tabuo |
1 | dom | 2 | 1 |
2 | samochód | null | null |
3 | okno | 1 | 3 |
but if I add where in which I compare id_de_tabuo column to null I dont't get any result.
SELECT tabuoj.id, tabuoj.tabuo, montritaj_tabuoj.id, montritaj_tabuoj.id_de_tabuo
FROM tabuoj LEFT JOIN montritaj_tabuoj
ON (tabuoj.id=montritaj_tabuoj.id_de_tabuo)
WHERE montritaj_tabuoj.id_de_tabuo=null
If I compare for example 1 like this:
SELECT tabuoj.id, tabuoj.tabuo, montritaj_tabuoj.id, montritaj_tabuoj.id_de_tabuo
FROM tabuoj LEFT JOIN montritaj_tabuoj
ON (tabuoj.id=montritaj_tabuoj.id_de_tabuo)
WHERE montritaj_tabuoj.id_de_tabuo=1
I get correct:
id | tabuo | id | id_de_tabuo |
1 | dom | 2 | 1 |
But I need rows with null in id_de_tabuo column. What I do wrong?
Try with IS NULL instead of = null like this
SELECT tabuoj.id, tabuoj.tabuo, montritaj_tabuoj.id, montritaj_tabuoj.id_de_tabuo
FROM tabuoj LEFT JOIN montritaj_tabuoj
ON (tabuoj.id=montritaj_tabuoj.id_de_tabuo)
WHERE montritaj_tabuoj.id_de_tabuo is null
Reason: Actually
montritaj_tabuoj.id_de_tabuo is null checks that the value is null. whereas
montritaj_tabuoj.id_de_tabuo = null checks that the value is equal to NULL which is never true.
Even NULL is not equal to NULL. You can check using this.
if(null = null)
print 'equal'
else
print 'not equal'
it will print not equal. Now try this
if(null is null)
print 'equal'
else
print 'not equal'
it will print equal.
Try just two simple select like
select * where id = null
and
select * where id != null
It's a common misconception about null.
Think null as the english word "whatever" in a opposition to "nothing" and you ill start to understand it better.
As sachim answered use
IS NULL
on your predicates.
When you filter on a left joined table in the where clause, the join becomes an inner join. To solve the problem, filter in the from clause, like this:
FROM tabuoj LEFT JOIN montritaj_tabuoj
ON (tabuoj.id=montritaj_tabuoj.id_de_tabuo)
and montritaj_tabuoj.id_de_tabuo is null
where clause starts here
I have 3 tables, USER, ENTRY (for entered products, not necessary to create a PRODUCT table), and USER_COLLECTION, which is a table inbetween USER and ENTRY, because an entry can have multiple users.
Basically:
User = USERID | USER_NAME
Entry = ENTRYID | ENTRY_NAME | ENTRYPRICE | ENTRY_DATE
Collection = COLLECTIONID | ENTRYID | USERID
I have a table with users that persist throughout the project. They can create entries (which is usually some kind of product with a price) and they can link multiple users to a certain entry (which can be selected from a list, hence the users persist throughout the project).
So for instance, my tables look like this:
User
--------------------------
user_id | user_name
--------------------------
1 | 'FOO'
2 | 'BAR'
3 | 'FOOBAR'
ENTRY
-----------------------------------------------------------------------
entryid | entry_name | entry_price | entry_date
-----------------------------------------------------------------------
0 | 'Banana' | 2.50 | 12/12/2012
COLLECTION
---------------------------------------
collectionid | entryid | userid
----------------------------------------
0 | 1 | 1
1 | 1 | 2
2 | 1 | 3
I have a Banana, with a price of 2.50 and 3 users linked to it, Foo, Bar and Foobar.
Now, I want to use this in my app and get the data; except I don't know where to start. I tried selecting the entry data, using that id to loop through the collection data, but that would mean I have two cursors open and it wouldn't work. Tried creating a join but I couldn't really make a good one, mainly because:
JOIN
---------------------------------------
collectionid | entryname | username
----------------------------------------
0 | Banana | FOO
1 | Banana | BAR
2 | Banana | FOOBAR
I can't iterate through this, because I would create multiple of the same entry objects in my Android code...
Hope I'm being clear on this.
if (cursor2.moveToFirst()) {
do {
Item i = new Item(<GET STUFF FROM CURSOR>);
i.addUser(new Person(<GET STUFF FROM CURSOR>)));
Log.d("TAG", i.getUsersPaying().size() + "");
} while (cursor2.moveToNext());
}
If I use this, I create mulitple instances of Item i. They'll all be Banana, whilst I should only have 1 item Banana, with multiple users added to it.
First, you might want to consider returning the IDs from your tables in your join query. Things would be a little easier if you returned the entryid column.
Just make a Map<Integer, Item> to store items that you have seen already in your loop. As you examine each cursor, check the map to see if you already have an instance. If you don't, just make a new one and insert it.
Let's assume your query results are:
JOIN
----------------------------------------------------
collectionid | entryname | entryname | username
----------------------------------------------------
0 | 1 | Banana | FOO
1 | 1 | Banana | BAR
2 | 1 | Banana | FOOBAR
2 | 2 | Apple | FOOBAR
You can modify your code as follows:
Map<Integer, Item> items = new HashMap<Integer, Item>();
if (cursor2.moveToFirst()) {
do {
int itemId = cursor2.getInt(1);
Item i;
if (items.containsKey(itemId))
i = items.get(itemId);
else
{
i = new Item(<GET STUFF FROM CURSOR>);
items.put(itemId, i);
}
i.addUser(new Person(<GET STUFF FROM CURSOR>)));
Log.d("TAG", i.getUsersPaying().size() + "");
} while (cursor2.moveToNext());
}
You need to maintain a dictionnary of your entities which are already loaded in memory. For instance in a background fragment which would be retained.
Basically you would do:
Item i = cacheFragment.createOrGetEntry( cursor.getLong( ENTRY_ID_COLUMN_INDEX ) );
Person p = cacheFragment.createOrGetPerson( cursor.getLong( PERSON_ID_COLUMN_INDEX ) );
Of course, your query must also return the IDs of all the rows you need (entryId and personId). But a join query is the way to do it efficiently, so keep what you did about that and just add the two missing ID columns.
a createOrGetPerson method would look like:
public Person createOrGetPerson(long id) {
Entry<Long, Person> p = personDictionnary.get( id ); // can be a HashMap or even better, a SparseArray
if (p==null) {
p = new Person(id);
personDictionnary.put(p); // Remember it for next time
}
return p;
}
You should also have a look at data persistence frameworks or ORM frameworks which are made to deal with this kind of problem (e.g. Hibernate, even though I don't know if that is working with Android).
I am building an android application which queries a database for a bus number, and bus departure time.
The tables are thus -
Table 1: Route - _id, routenumber
Table 2: Routetimedetails - _id, routetime, routeid
My current query is this
select routenumber, route._id, routetime from route, routetimedata where route._id = 2 and routeid = route._id
and the result shows up like this
>
routenumber | route._id | routetime
-------------------------------------
BIAS10 | 2 | 0945
BIAS10 | 2 | 1810
BIAS10 | 2 | 1945
BIAS10 | 2 | 0710
is there a way in sqlite3 to show the result in a single column like this -
BIAS10 | 2 | 0710, 0945, 1810, 1945
Thanks
Mukul
I find that the Group_Concat() function does this easily
select routenumber, route._id, Group_concat(routetime) from route, routetimedata where route._id = 2 and routeid = route._id