Many-to-Many Query in One Cursor Without Repeating Data - android

So, I'm going to say that I have three tables as follows:
POSTS POSTS_TAGS TAGS
+-----+-----------+ +---------+--------+ +-----+-------+
| _id | title | | post_id | tag_id | | _id | title |
+-----+-----------+ +---------+--------+ +-----+-------+
| 0 | foo | | 0 | 1 | | 0 | baz |
+-----+-----------+ +---------+--------+ +-----+-------+
| 1 | bar | | 0 | 2 | | 1 | quux |
+-----+-----------+ +---------+--------+ +-----+-------+
| 1 | 0 | | 2 | corge |
+---------+--------+ +-----+-------+
| 1 | 2 |
+---------+--------+
Is there any way to formulate a query with SQLite such that I could then have a cursor with the following data in it:
row1 = <foo, <quux, corge>>
row2 = <bar, <baz, corge>>
As opposed to:
row1 = <foo, quux>
row2 = <foo, corge>
row3 = <bar, baz>
row4 = <bar, corge>
However, I severely doubt that there is anything that will give me precisely that, so I guess my real question is, what is the best way to formulate a query such as this, so that I can pass it back to my activity, and it would be able to return all this data to the activity? Or am I really going to need to iterate through my cursor again afterwards to "pick up" all the extra data and reorganize it myself.

Got the solution:
SELECT posts._id, posts.title, GROUP_CONCAT(tags._id) AS tags_id, GROUP_CONCAT(tags.tag_name) AS tags_name FROM posts
LEFT OUTER JOIN posts_tags ON posts_tags.post_id=posts.post_id
LEFT OUTER JOIN tags ON posts_tags.tag_id=tags.tag_id
GROUP BY posts._id;
Please adapt the query to your problem :)
You can find SQLite documentation about concat(x) and concat(x,separator) here.
Anyway you can also follow my problem on google group.

Related

Subqueries in sqlite. Count the number of selected items in a group

When forming a tree of objects, it is necessary to know whether all elements in the group are selected or not.
A group can have subgroups, unlimited nesting. You want to know if all items are selected or multiple items are selected or nothing is selected.
Is it possible to make one query in SQLite, and find out how many items are selected in a group (including subgroups) and the total number of objects in a group(including subgroups)?
I need to find out if all nested elements of a group are selected or not all or nothing is selected
As a result, you need to get such a state for the group:
sealed class GroupSelectState {
object None: GroupSelectState()//nothing selected
object Any: GroupSelectState()//at least one item is selected in a folder or in subfolders
object All: GroupSelectState()//all objects in the folder and subfolders are selected
}
Here is the structure of the tables:
Group table
| id | name | parentId |
| 1 | old | null |
| 2 | gaz | 1 |
| 3 | kamaz| 1 |
| 4 | 54901| 3 |
Object table
| id | name | groupId |
| 1 | Kamaz 777 | 3 |
| 2 | Kamaz 767 | 3 |
| 3 | Kamaz 677 | 4 |
| 4 | Kamaz 766 | 4 |
| 5 | Gaz 556 | 2 |
Table of selected objects (if the object is not in this table, then it is not selected)
| id | objectId | isChecked |
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 0 | // if the object has never been selected, then the table will not have a record for this object
For representing hierarchical data in sql database, the Nested Set Approach was invented. Read more on this on wikipedia: https://en.m.wikipedia.org/wiki/Nested_set_model
First get all child and sub child groups for the selected group
;WITH tempTable AS (
SELECT
folderId,
name,
parentId
FROM TreeItemEntity
WHERE folderId = 20058 (groupId)
UNION ALL
SELECT
t.folderId,
t.name,
t.parentId
FROM
TreeItemEntity t
INNER JOIN tempTable c
ON t.parentId = c.folderId
)
SELECT *
FROM tempTable
Result
Далее получаем объекты для этих групп
SELECT * objects where groupId in resultTableIds
returned all objects for select group and all child groups. Then we can check the selected objects or not

Inner Join two tables and return greatest value from second table for each entry in first table

How would I construct a query in SQLite that selects every row from a TABLE1, and also selects one row from a TABLE2 where:
There is a match between an id value from TABLE1, and;
If there is more than one id match in TABLE2, only the highest value in another DATE column is returned.
Here is the table arrangement I have right now. The value in the r_identifier column corresponds to the t_id value in TABLE1:
TABLE1 ("Tanks")
+------+--------------+-------+
| t_id | t_name | t_vol |
+------+--------------+-------+
| 1 | A Tank | 23 |
| 2 | Another Tank | 48 |
+------+--------------+-------+
TABLE2("Readings")
+------+--------------+--------+---------+
| r_id | r_identifier | r_date | r_value |
+------+--------------+--------+---------+
| 0 | 1 | 5000 | 5 |
| 1 | 1 | 6000 | 7 |
| 2 | 2 | 7000 | 4 |
| 3 | 1 | 8000 | 3 |
+------+--------------+--------+---------+
And here is the table I would like to return from my query. Because there are multiple entries with the r_identifier of 1, only the one with the highest value in r_date is returned:
+------+--------------+-------+------+--------------+--------+---------+
| t_id | t_name | t_vol | r_id | r_identifier | r_date | r_value |
+------+--------------+-------+------+--------------+--------+---------+
| 1 | A Tank | 23 | 3 | 1 | 8000 | 5 |
| 2 | Another Tank | 48 | 2 | 2 | 7000 | 4 |
+------+--------------+-------+------+--------------+--------+---------+
The closest I've been able to manage so far is with the following statement, inspired by this answer:
SELECT t.*, r.* FROM t INNER JOIN r ON t._id=r_identifier ORDER BY r_date DESC LIMIT 1
This returns the correct values, but for only one "tank" - the first one in the table.
Edit
I forgot to mention in my original question that I wanted to retrieve every value in TABLE1 even if there were no entries in TABLE2 that had a matching value in the r_identifier column. Using Gordon Linoff's answer as a guide though I was able to come up with the following which is working well:
SELECT t.*, r.*
FROM t LEFT OUTER JOIN
r ON t._id=r_identifier
WHERE
(r_date IS NULL) OR
(r_date=(SELECT MAX(r2.r_date)
FROM r r2
WHERE r.r_identifier=r2.r_identifier));
One method is to use a WHERE clause with a correlated subquery to get the maximum date:
SELECT t.*, r.*
FROM t INNER JOIN
r
ON t._id = r.r_identifier
WHERE r.r_date = (SELECT MAX(r2.r_date)
FROM r r2
WHERE r.r_identifier = r2.r_identifier
);

get values from 2 different entities with greendao 3

Problem: How I can get 2 values from 2 different tables? I'm replacing android Content Provider with greenDao. With Content provider you can define a sql view but this is not possible with greenDao.
So I tried to use joins but greenDao return me only one list entity.
What is the best method in greenDao to get 2 values from 2 different entities?
Example:
|Table a| | Table b |
| id | descr | b_Id | | id | hues | hex |
| 1 | place | 1 | | 1 | 2 | #000|
| 2 | sea | 1 | | 2 | 3 | #111|
| 3 | name | 2 | ...
... ...
How can I get the following object or similar?
C c = new C(d.getDescr(), d.getHex());
thanks in advance.
Consider using relations. If you have an object a, you could get b via a.getB().

Traversing directed cyclic graph in SQLite on Android

Say I have two SQL tables: NODES and EDGES
Nodes contains information pertaining to each node, and each row in EDGES contains a directed edge between two nodes.
i.e.
Table EDGES
|edge_id | node_from_id | node_to_id |
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 4 | 3 | 5 |
| 5 | 6 | 10 |
| 6 | 6 | 11 |
| 7 | 7 | 8 |
Querying the table for all the children of a node is trivial, but what if I want to have a list of all the children of all the children of a node? Or better yet a list of all the edges that create a tree of the node's descendants? Note that the graph may be cyclical and is not fully connected.
For example, I want to select all the descendant edges of node 1:
QUERY Results:
|edge_id | node_from_id | node_to_id |
| 1 | 1 | 2 |
| 2 | 1 | 3 |
| 3 | 2 | 1 |
| 4 | 3 | 5 |
In SQL and SQLite 3.8.3+ I could use something like a Common Table Expression (CTE) to do this and there are many answers on SO to that effect. But on Android I'm currently limited to SQLite 3.4.0 which doesn't support CTE's.
I could programmatically query each level of the tree, but I would prefer to do this all in SQL if possible. Is there a neat way to accomplish this given my limitations?
CTEs exists because there is no other way to do recursive queries.
You have to query the children step by step.

Continuous numbering of a the retrieved data in an extra column

I want to get a numbered cursor when I use a SELECT DISTINCT query.
Table:
| _id | Name |
| 1 | Jones |
| 2 | Smith |
| 3 | Jones |
| 4 | Taylor|
| 5 | Brown |
| 6 | Brown |
| 7 | Brown |
What I want to get a cursor like this:
| _id | Name |
| 1 | Jones |
| 2 | Smith |
| 3 | Taylor|
| 4 | Brown |
I tried a lot but it wasn't working.
Sometimes there were no unique values and sometimes I get the following error when I selected an Item:
08-22 22:18:15.413: ERROR/AndroidRuntime(1053): java.lang.IllegalStateException: this should only be called when the cursor is valid
Thanks for your help!
I think the easiest method is to use a temporary table:
'create temporary table bat as select distinct name from yourtable;
select rowid, * from bat ; '

Categories

Resources