ActiveAndroid: Subqueries? - android

I'm using ActiveAndroid in an app for database interaction. I need to join a few tables and then filter the results, which I would usually accomplish using a SQL query with a sub-query.
How might one accomplish a sub-query using ActiveAndroid?
If a sub-query cannot be done, is there a way to only return unique Model objects? The join in my query has the effect of creating duplicate rows in the join table, but I only want one instance of each Model to be returned.
EDIT: Providing more info
The model I'm trying to retrieve is called Profile.
With regard to the query, there are 3 tables:
Profiles, Roles, and ProfileRoleJoins
There is a many-to-many relationships between Profiles and Roles and that relationship is maintained by the join-table called ProfileRoleJoins.
My goal is to obtain all Profiles that have a certain "event_id" and are connected to one or more Roles specified by a list of Role types.
Of interest to this query are the following fields:
Profiles
Id
event_id (not a foreign key, just a data field)
Roles
Id
type (TEXT)
ProfileRoleJoins
profile (foreign key)
role (foreign key)
What I've Tried
String eventId = //provided as input to this function
String[] roles = //array of "types" of roles we want to limit to
String whereClause = //built in a loop, looks like "Roles.type = ? OR Roles.type = ?..."
new Select()
.from(ProfileEntity.class)
.where("event_id = ?", eventId)
.join(ProfileRoleJoinsTable.class)
.on("Profiles.Id = ProfileRoleJoins.profile")
.join(RoleEntity.class)
.on("ProfileRoleJoins.role = Roles.Id")
.where(whereClause, roles)
.execute();
The above query has the problem that it returns duplicate Profiles because a single Profile can be associated with multiple Roles which creates duplicates during the join process.
I need to retrieve a list of unique Profiles.
I tried using Distinct(), but that qualifier applies per set of columns - I need entire Profiles back.
The way I would normally accomplish the uniqueness is by doing the above query in a sub-query and return only DISTINCT Profiles.Id values. Then I would run a filter in the main query against the original Profiles table.

I still don't know how to do sub-queries with ActiveAndroid (if its even possible), but I found out the source of my problem. I was using an outdated version of the library and there was some kind of error in the query system that screwed up the results. With the current version of the library I do not get duplicates.

Related

Best practice for Android Room database design: using multiple classes/interfaces or multiple queries

I'm newbie to android and am learning the basics of kotlin/Room. As I head down the rabbit hole of data classes, DAOs joining tables, I am trying to understand why so many table/interfaces are used where multiple queries could achieve the same outcome?
Example: an application contains an address book of business contacts. A user can select one or more contacts for their address book from a large list. The aim is to only populate the users address book with the information of the contacts they have selected.
This would require:
A User table: containing unique user information for many users (userId, name, address...etc.)
A Contacts table: containing unique contact information for many contacts (contactId, name, address...etc.)
A joining table: containing the contact selections of each user (userId and contactId)
A UserWithContacts table: containing embedded user objects with a relation to the contact object in the joinging table.
The purpose of the UserWithContacts table as I understand it is to query directly and get a list of contact objects that have been selected by a specific user.
This structure, with adjoining DAOs, makes for a number of classes/interfaces/etc to keep track of.
Why is it better to take this approach and not simply query the joining table for a list of contactIDs based on a given userId, followed by a second query that returns the contact objects from the contact table with contact information? This would not required the additional UserWithContacts table or DAO interface.
For Example:
//Get a list of contactId's that have a common UserId
#Query("SELECT contactId FROM joiningTable WHERE userId =:userId")
fun getAllUserContactIds(userId: String): List<String>
//Get a list of Contacts objects from are contained within a list of Contact Ids
#Query("SELECT * FROM contactTable WHERE contactId IN (:contactIds)")
fun getAllUserContacts(contactIds: List<String>): List<Contact>
This pair of queries provides an equivalent list of Contact objects that can be used to populate the address book.
Can anyone describe why it is preferred to use multiple classes/interfaces instead of multiple queries?
Thanks in advance for your thoughts.

Firebase query for multiple where condition

I need equivalent query of
SELECT PlayerName FROM GameScores
WHERE Department = 'HR' OR Department = 'IT' OR Department = 'Marketing'
In Firebase for android , I don't want multiple call, just one request and get all data that match with where clause key. How I can do it?
The only way to filter a property on multiple values in Firebase is if those values are in a range. For example, you could get all items matching your values with:
ref.child("GameScores")
.orderByChild("Department")
.startAt("HR")
.endAt("Marketing")
The problem with this is that it also matches scores from other departments whose name is between HR and Marketing, such as
There is no way in either the Firebase Realtime Database or Cloud Firestore to pass multiple separate values into a query. You will have to execute a separate query for each value and merge them client-side.
Also see:
firebase equivalent to sql where in ()

Saving a changing amount of Values in a SQL-Database

i am really stuck at this point of my android app development.
What i need is a way to save a changing amount of int or string-values (in a sql database). Yet im not even sure if this is the right approach, but let me explain:
In the app i am currently working on, you are able to create certain "events". Users should be able to apply for such events.
I have an external database with 2 tables:
first one for users - every user has a unique ID
second one for events - every event has a unique ID
I need each event to know what users applied for it. And i need each user to know what events they applied for.
I was thinking to save the Event-IDs in the User-Table and vice versa.
I just dont know how to do that since the amount of applicants/ID's can change. Is there a way to save Arrays in the database which can easily be edited (e.g. +/- one ID) and read?
Is this even the right way? I am very happy for any advise!
Thanks in advance!
What you seem to want is a many-to-many relationship. A user can be part of many events, and an event can have many users. That requires an additional table though:
Table: User Columns: UserId, Name, ...
Table: Event Columns: EventId, Name, ...
Table: UserEvents Columns: UserId, EventId, ...
In the new table, UserEvents, you would store the UserId's and EventId's like this:
UserEvents
UserId EventId
1 1
2 1
1 2
This means that if you selected UserId 1, the query would return EventId 1 & 2. If you selected EventId 1 the query would return that UserId 1 & 2 would be attending.
This is the standard and recommended way to deal with many-to-many. It's very flexible and can easily be scaled.
You could either use a Compound key (Composite Key) for this table, or create a column specifically as a Primary Key. The code below can be used, and manipulated, to create both your table and Compound/Composite key (I'm guessing on data types).
CREATE TABLE UserEvents
(
[UserId] INT NOT NULL,
[EventId] INT NOT NULL
CONSTRAINT PK_UserEvents PRIMARY KEY NONCLUSTERED ([UserId], [EventId])
)
I would add a third table (e.g. UserEvents) to store which events a user has applied for, along with other relevant attributes (e.g. ApplicationTime, ApplicationStatus). This association would have a foreign key relationship back to the related tables and resolve the many-to-many relationship between users and events.
What you have there is called a "many-to-many" relationship between to tables which can only be resolved by the introduction of a third table between your two tables that stores the associations.
This table would contain the User-ID and the Event-ID as foreign keys (and maybe additional information).

Data synchronization between two or Android devices and website

I am building an app that allows users to insert data and synchronize with website. User can insert data on the website as well. There are two entity tables (T1 and T2) and one N-M relation table (TR).
Data Structure (it's just illustrative):
T1 (_id, name, modified)
T2 (_id, name, modified)
TR (t1_id, t2_id)
The problem I am facing is data synchronization of IDs. E.g. Device A1 and A2 are offline and record is inserted on both, with the ID = 1. After they are online sync starts and there is a conflict with IDs. I thought about introducing an extra column gid - something like global ID. So the structure would be:
T1 (_id, name, modified, gid)
T2 (_id, name, modified, gid)
TR (t1_id, t2_id, t1_gid, t2_gid)
Global ID would be assigned by website.
But I not sure whether this is a good approach or not (never done anything like this before and cannot tell if there will be any future problem).
You have to use additional ids, suppose network_id, generate all network_ids on the server and use local ids on devices (e.g. UUID). When you are sending create entity request server will generate a real id and return it to you, so you can update a local database with network_id. It is important to use network_id as main field and local_id only if you don't have network_id.

Dynamic Tables in Android SQLite

My question involves databases - The scenario is this:
I have an app that tracks when people borrow items. I have an existing table which tracks who they are, what they have borrowed and so on. What I would like to do is create a separate table to track what the person has borrowed, their contact info, if they returned it, etc.
My idea to do this would be to create a Dynamic table in SQL that would hold the records for 1 person, ie
John Smith
DVD; July 12, 2012; Returned in good condition; etc
As I'm still learning, I wanted to know if:
This is possible, feasible or if there is a smarter way of going about it.
Your answer depends on your scenario;
If you are only interested with "who" borrowed "what" (currently) and not "when" except last occurance, and you are assuming there are always only 1 copy of an item, then you can use one to one relation as:
CREATE TABLE Person
(
PersonId int IDENTITY(1,1) NOT NULL,
Name nvarchar(30) NOT NULL,
Surname nvarchar(30) NOT NULL,
BorrowItemId int NULL FOREIGN KEY REFERENCES Item UNIQUE,
BorrowDate datetime NULL,
ReturnDate datetime NULL,
ReturnCondition nvarchar(50) NULL,
CONSTRAINT PK_Person PRIMARY KEY CLUSTERED (PersonId ASC),
)
CREATE TABLE Item
(
ItemId int IDENTITY(1,1) NOT NULL,
ItemDescription nvarchar(50) NOT NULL,
CONSTRAINT [PK_Item] PRIMARY KEY CLUSTERED (ItemId ASC)
)
If you have multiple copies of each item you should remove the UNIQUE key on BorrowItemId changing relation to one to many. In case;
To see the items borrowed and returned with person information:
SELECT PersonId, Name, Surname, ItemDescription, ReturnDate, ReturnCondition
FROM Person INNER JOIN Item
ON BorrowItemId = ItemId
WHERE BorrowItemId IS NOT NULL
AND ReturnDate IS NOT NULL
You can add PersonId filter in WHERE clause to query for specific person
This isn't a good design since you can insert records without date information or you can even have records with date info but no related BorrowItemId. I suggest using many to many and keep historic data (can be handy) or overwrite using update each time the person borrows a new item
Their contact information could be linked into the table which tracks who they are.
If you have not created a table yet for the returns then I suggest you reference the borrowing table's ID and set in the borrowing table a flag to say this item has been returned.
I am not too sure why you would want to create a new table to collate all the information. If you want to get all the information together then I suggest using the SQL keywrod JOIN when preparing statements. If you really want to store the information later on in a table you can but it will just be duplicates in your database.
A tutorial on the different types of joins you can do : http://www.w3schools.com/sql/sql_join.asp
It is definitely possible to do as you describe. It really isn't a very good strategy, though. Your new table is, exactly, equivalent to an additional column in the existing table that tags the row as belonging to a specific individual.

Categories

Resources