Issue in join query of multiple tables sqlite - android

hello friends i have four tables as below
property_master --> "p_id" , "p_name" , "p_address" , "p_city" , "p_state" ,"r_id"
property_unit -->"unit_id" , "p_id" , "unit_name" ,"r_id"
unit_info --> "unit_info_id" ,"unit_id" INTEGER,"p_id" ,"p_bathroom" ,"p_bedroom" ,"p_size" ,"p_rent" ,"p_isrent" ,"u_note" ,"r_id"
tanant_master --> "t_id" , "t_name" ,"t_cell_no" ,"t_phone_no" ,"t_mail" ,"t_deposit" ,"r_id"
property_assign--> "t_assign_id" , "unit_info_id" , "t_id" , "t_start_date" , "t_end_date" , " t_rent_due_day" , "t_lease_alert" , "t_status" ,"r_id"
and my query is as below
Select p_name As "Property",
p_id AS "PID",
(Select Count(unit_id) from property_unit where property_master.p_id=property_unit.p_id )As "UnitCount",
(Select Count(unit_info_id) from unit_info where unit_info.unit_info_id=property_assign.unit_info_id )As "TenantCount"
From property_master ,property_assign Group by property_master.p_id
i need total tenant count propertywise but when i run above query it gives me only first property tenant count for all property any idea how can i solve it?

Try something like this:
select a.PID,
MAX(a.Property) as "Property",
COUNT(a.unit_id) as "UnitCount",
SUM(a.TenantCount) as "TenantCount"
from (
select property_master.p_id as "PID",
MAX(property_master.p_name) as "Property",
property_unit.unit_id,
COUNT(property_assign.t_id) as "TenantCount"
from property_master
JOIN property_unit ON property_master.p_id = property_unit.p_id
JOIN unit_info ON unit_info.unit_id = property_unit.unit_id
JOIN property_assign ON unit_info.unit_info_id = property_assign.unit_info_id
group by property_master.p_id, property_unit.unit_id
) a,
group by a.PID
Note 1 You probably need to use LEFT OUTER JOIN instead of JOIN depends on your data structure (can be property_assign empty or not?)
Note 2. Sorry, I couldn't test it. You should do it yourself.

Related

Query that brings all the parents whose children meet a certain criteria

I need a query that brings all the parents whose children meet a certain criteria.
So far this is giving me something different than expected:
#Transaction
#Query("SELECT * FROM piece_unit_table put WHERE (SELECT et.date_of_creation FROM expense_table et WHERE et.piece_unit_parent_id = put.piece_unit_id) = :dateOfExpenseCreation AND project_id = :projectId")
public abstract LiveData<List<PieceUnit>> getPieceUnitsWhereDateOfExpenseCreation(long dateOfExpenseCreation, int projectId);
A more readable version of the same code above:
SELECT *
FROM piece_unit_table put
WHERE (
SELECT et.date_of_creation
FROM expense_table et
WHERE et.piece_unit_parent_id = put.piece_unit_id
) = :dateOfExpenseCreation
AND project_id = :projectId
At first I thought I got a jackpot with that one because it gave me responses on the first try (I usually spend a whole day just thinking about the structure of the query, I hate them), I never gave it too much thought, but the days passed by and it stopped giving me responses, so I'm guessing that maybe, the query was comparing some other dates inside the WHERE clause, more precisely, the dates on which the pieces where created.
Now that I reread it again it looks like a pretty bad query...
The way in which I'm storing dates (from the children side):
public void insertExpense(Expense expense) {
long now = Converters.dateToTimestamp(LocalDate.now());
expense .setDate_of_creation(now);
long edited = System.currentTimeMillis();
expense .setLast_edited(edited);
Log.println(Log.WARN, TAG, "insertExpense: date of creation is: " + expense.getDate_of_creation());
Log.println(Log.WARN, TAG, "insertExpense: expense project is: " + expense.getParent_project_id());
Log.println(Log.WARN, TAG, "insertExpense: expense piece parent is: " + expense.getPiece_unit_parent_id());
insert(expense);
}
The observer side:
Log.println(Log.ERROR, TAG, "getPieceUnitGroupedByExpenseProductsAtDateAndProject: specific date is: " + specificDate);
Log.d(TAG, "getPieceUnitGroupedByExpenseProductsAtDateAndProject: project id is: " + project);
MyObserver
.observeOnce(
pieceUnitRepository.getPieceUnitsWhereDateOfExpenseCreation(
specificDate,
project
),
pieceUnits ->
{
Log.d(TAG, "getPieceUnitGroupedByExpenseProductsAtDateAndProject: piece units are: " + pieceUnits);
if (pieceUnits != null && pieceUnits.size() > 0) {
PieceUnit p = pieceUnits.get(0);
Log.println(Log.WARN, TAG, "getPieceUnitGroupedByExpenseProductsAtDateAndProject: Hello there ;) : " + p.getBeginning_date());
}
The Logd's:
insertExpense: date of creation is: 18469
insertExpense: expense project is: 1
insertExpense: expense piece parent is: 4
getPieceUnitGroupedByExpenseProductsAtDateAndProject: specific date is: 18469
getPieceUnitGroupedByExpenseProductsAtDateAndProject: project id is: 1
getPieceUnitGroupedByExpenseProductsAtDateAndProject: piece units are: []
I'm not asking for a full solution, but any input could point me in the right direction, so thanks in advance.
Final answer (from second update):
SELECT
put.*
FROM piece_unit_table put
WHERE
EXISTS(
SELECT
1
FROM
expense_table et
WHERE
et.date_of_creation = :dateOfExpenseCreation AND et.piece_unit_parent_id = piece_unit_id
) AND
put.project_id = :projectId
EDITS
First answer :
In SQL there seems to be a function that helps on these cases:
all or not exist
https://stackoverflow.com/a/42439405/11214643
In the SQLite case there doesn't seem to be a direct equivalence, and every solution seems to be a case by case workaround depending on the type of clause.
In my case I LEFT JOIN-ed the children table, but group by-ing it before the join to avoid repeated rows on the left table.
As is expected, it was during the child table sub-query, that I filtered the table by their date condition
SELECT put.*
FROM piece_unit_table put
LEFT JOIN(
SELECT
piece_unit_parent_id
FROM
expense_table et
WHERE
et.date_of_creation = :dateOfExpenseCreation
GROUP BY
et.piece_unit_parent_id
) et1
ON
et1.piece_unit_parent_id = put.piece_unit_id
WHERE
put.project_id = :projectId
UPDATE:
It seems that behind curtains(either be SQLite or the ROOM interface), the LEFT JOIN is happening before the sub-query executes its own WHERE clause, as a result, the query is giving me parents, even when there are no children that meet the criteria, so the solution was to bring an additional column from the child temp table to the 'front', and check for it's non null-ability.
SELECT
put.*,
et1.puId AS expPuId
FROM piece_unit_table put
LEFT JOIN(
SELECT
piece_unit_parent_id AS puId
FROM
expense_table et
WHERE
et.date_of_creation = :dateOfExpenseCreation
GROUP BY
et.piece_unit_parent_id
) et1
ON
et1.puId = put.piece_unit_id
WHERE
put.project_id = :projectId AND expPuId NOT NULL
UPDATE 2:
Thanks to #forpas
The EXISTS and NOT EXISTS operators are in fact supported by SQLite, also, what was bringing me parents even when no children met the criteria was the second WHERE clause that was applied directly to the left table, but even if there was no clause applied to this table, it would've still gave me answers, because that's how LEFT JOIN works, if there are no matches it fills them with NULL's.
Here is a query that has the expected result, but does it better.
SELECT
put.*
FROM piece_unit_table put
WHERE
EXISTS(
SELECT
1
FROM
expense_table et
WHERE
et.date_of_creation = :dateOfExpenseCreation AND et.piece_unit_parent_id = piece_unit_id
) AND
put.project_id = :projectId

SQLite query works on android 4.4, but crashes on android 5.0

The following SQLite query works fine on android 4.4 and below, but it causes an exception: "android.database.sqlite.SQLiteException: ambiguous column name: number (code 1):......" on android 5.0 and later. I checked the SQLite release documents, but did not see any changes that can effect my work. Is there any thing that I missing?
select * from
(
select
'0' as queryid,
CNCT._id,
coalesce(case when length(C.abId)=0 then null else C.abId end,
(
select
addrBkId from numbers as nm,
contacts as cot
where nm.number=coalesce(C.number,S.Number) and nm.contactID = cot._id
order by cot.lastMod desc limit 1)) as addrBkId,
coalesce(
case when length(C.abId)=0 then null else C.abId end,
(
select
addrBkId from numbers as nm,
contacts as cot
where nm.number=coalesce(C.number,S.Number) and nm.contactID = cot._id
order by cot.lastMod desc
limit 1
)
) as uqAddrBkId,
CNCT.displayName,
CNCT.firstName,
CNCT.lastName,
CNCT.favorite,
coalesce(C.location,
(
select
location from calls as css
where css.number = S.Number
)) as location,
0 as numberType,
coalesce(C.number,S.Number) number,
N.txt,A.type,
coalesce(A.callID,A.smsId) actId,
max(A.startEpoch) as maa,
max(A.startTime),
strftime('%w',datetime(A.startEpoch,'unixepoch','localtime'))+0 dayOfWeek,
strftime('%W',datetime(A.startEpoch,'unixepoch','localtime'))+0 weekOfYear,C.duration,
case
when C.callResult='vmail' then 'vmail'||C._id
when C.callType='callin' and C.callResult='missed' then 'missed'
else C.callType end as newCallType,
C.callResult,
C.extension,
C.msgId,
C.audioUrl,
C.name,
C.state,
C.syncParams,
S.smsId,
S.dir,
S.state,
N.noteId,
N.color from activity as A
left outer join calls C on A.callId=C.callId
left outer join sms S on A.smsId=S.smsId
left outer join contacts CNCT on coalesce(case when length(C.abId)=0 then null else C.abId end,
(
select addrBkId from numbers as nm,
contacts as cot
where nm.number=coalesce(C.number,S.Number) and nm.contactID = cot._id
order by cot.updated desc
limit 1)
)=CNCT.addrBkId
left outer join
(
select * from notes as nt
order by nt.lastMod asc
) as N on CNCT.addrBkId=N.addrBkId
where (C.state<>5 or C.state is NULL) and (C.callResult<>'abandoned' or C.callResult is NULL)
group by newCallType,number,weekOfYear,dayOfWeek
order by max(A.startEpoch) asc
)
group by _id
order by maa desc
limit 3
... where nm.number=coalesce(C.number,S.Number) ...
... where nm.number=coalesce(C.number,S.Number) ...
... where css.number = S.Number) ...
... coalesce(C.number,S.Number) ...
... where nm.number=coalesce(C.number,S.Number) ...
... group by newCallType,number,...
^^^^^^
All occurences of number are qualified with a table alias, except the last one. That one indeed is ambiguous.

Sqlite, i have a date field, doesn't return data

I have a to tables, and the field _fecha is a TEXT type colunm, and i consulted several examples and nothing.
SELECT mae_movintos._id
, mae_movintos._fecha
, mae_movintos._tipo
, mae_movintos._origen
, mae_movintos._destino
, mae_movintos._category
, mae_movintos._monto
, mae_movintos._orden
FROM mae_movintos, mae_cuentas
WHERE mae_cuentas._id = mae_movintos._id
AND strftime('%s',mae_movintos._fecha) = strftime('%s','2016-10-10')
You need to use JOIN if you want to query two tables.
SELECT _id
, _fecha
, _tipo
,_origen
, _destino
, _category
, _monto
, _orden
FROM mae_movintos
JOIN mae_cuentas ON mae_cuentas._id = mae_movintos._id
AND strftime('%s',mae_movintos._fecha) = strftime('%s','2016-10-10')
I finally managed to make it work, it was a small detail in the JOIN
SELECT mae_movintos._id
, mae_movintos._fecha
, mae_movintos._tipo
, mae_movintos._origen
, mae_movintos._destino
, mae_movintos._category
, mae_movintos._monto
, mae_movintos._orden
FROM mae_movintos
JOIN mae_cuentas ON (mae_cuentas._id = mae_movintos._origen)
WHERE mae_cuentas._usuario = ?
AND strftime('%s',mae_movintos._fecha) = strftime('%s','2016-10-10')
the error is that i had the following:
JOIN mae_cuentas ON (mae_cuentas._id = mae_movintos._id )
it was resolved by changing the reference:
JOIN mae_cuentas ON (mae_cuentas._id = mae_movintos._origen )

Fetch data from 3 Tables

I have 3 Tables
1 Customers
-c_id
-c_name
2 Debit_Master
-transaction_id
-c_id
-amount
3 Credit_Master
-transaction_id
-c_id
-amount
Now i want data like this : Customer Name and Total amount(credit amount - debit amount) of each customer .
I want query to fetch data in my listview with two columns 1- Customer Name , 2- Total amount
Try this SQL statement:
SELECT
Customers.c_name as CustomerName,
SUM((CASE
WHEN Credit_Master.amount IS NULL THEN 0
ELSE Credit_Master.amount END -
CASE
WHEN Debit_Master.amount IS NULL THEN 0
ELSE Debit_Master.amount END)) as TotalAmount
FROM Customers
LEFT JOIN Debit_Master on Customers.c_id = Debit_Master.c_id
LEFT JOIN Credit_Master on Customers.c_id = Credit_Master.c_id
GROUP BY Customers.c_id
Try something like this
SELECT Customers.c_name as name , (Credit_Master.amount - Debit_Master.amount) as total FROM Customers JOIN Debit_Master on Customers.c_id=Debit_Master.c_id JOIN Credit_Master on Customers.c_id=Credit_Master.c_id

Sqlite Android order by & group_concat

I'm using the sqlite3 : 3.8.2 with sqliteman (Ububuntu 14.04) to try the query that I need in my program Android.
Android version 4.0+.
I have 3 table to use to obtain data
I found this problem:
when I use this query in sqliteman
SELECT st.nome
AS nome,
st.cognome
AS cognome,
(SELECT ae.usercode
AS usercode
FROM assenze ae
WHERE st.ultimo_evento = ae.fk_evento)
AS ultimo_evento,
(SELECT
GROUP_CONCAT(
ev.nome_evento, ", "
)
AS nome_evento
FROM eventi ev
WHERE ev.studente_id = st.id
)
AS nome_evento
FROM studenti st
WHERE st.classe_ident ='4297'
ORDER BY st.cognome
the output is:
EP, USC, R1, R, A ... perfect for me
but when I use it in android with db.rawQuery() the result is
A, EP, R, R1, USC ... no good for me
also seems to be the same result of this query (execute in sqliteman and android):
SELECT
st.nome AS nome,
st.cognome AS cognome,
ae.usercode AS ultimo_evento,
GROUP_CONCAT(
ev.nome_evento, ", "
)
AS nome_evento
FROM studenti st
LEFT JOIN eventi ev
ON st.id = ev.studente_id
LEFT JOIN assenze ae
ON st.ultimo_evento = ae.fk_evento
WHERE st.classe_ident ='4297'
GROUP BY st.id
ORDER BY st.cognome
Probably it's my fault but I'm still trying to find a solution...
Thanks
seems that it works also without ORDER BY ev.data_ora_evento. But in android still not working...
The group_concat() documentation says:
The order of the concatenated elements is arbitrary.
However, you could try to force an order by executing group_concat() on a subquery that is sorted:
SELECT GROUP_CONCAT(ev.nome_evento, ", ") AS nome_evento
FROM (SELECT nome_evento
FROM eventi
WHERE studente_id = st.id
ORDER BY whatever) AS ev

Categories

Resources