Sqlite Android order by & group_concat - android

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

Related

Android sqlite update statement with from does not work

I am trying to create a trigger like below in sqlite android. It works fine in other sqlite engine but shows syntax error in android. Please help me to make this update statement work.
create trigger if not exists trigger_cascade_update_carry_forward
after update on cf_details
begin
update cf_details set cf = c_f from (with recursive dates_after(d) as
( values(new.date) union
select strftime('%Y-%m',d||'-01','+1 month') as next_month
from dates_after where exists(select 1 from cf_details where date = next_month and account_id = new.account_id))
select d,c_f from dates_after,(select cf+net as c_f from cf_details where account_id = new.account_id and date = strftime('%Y-%m',(select d from dates_after order by d limit 1)||'-01','-1 month'))) where date = d;
end;

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.

How to insert a table in to group in Corona SDK (.Lua)?

I get error message when i try to insert a table into a group
My table code is containing images
Here is the code i am using for the table
local myJoints = {}
for i = 1,5 do
local link = {}
for j = 1,17 do
link[j] = display.newImage( "link.png" )
link[j].x = 121 + (i*34)
link[j].y = 55 + (j*17)
physics.addBody( link[j], { density=2.0, friction=0, bounce=0 } )
-- Create joints between links
if (j > 1) then
prevLink = link[j-1] -- each link is joined with the one above it
else
prevLink = wall -- top link is joined to overhanging beam
end
myJoints[#myJoints + 1] = physics.newJoint( "pivot", prevLink, link[j], 121 + (i*34), 46 + (j*17) )
end
end
and here is the code for group
GUI:insert(myJoints);
i have my background image in the GUI group and it is covering the table.
I don't know if it is actually possible to insert table into a group
Any help please
Thanks in Advance!
You can't insert a table into a group using the "insert" method because that method is looking for a display object. Try calling GUI.myJoints = myJoints. Also keep in mind that your table just references your display objects, which is different from having them in a group.

select query with join is selecting data slowly from database in android

i have select query as follows
SELECT DISTINCT tt.firstname,
tt.lastname,
tc.caseid,
tt.courtcode AS courtid,
tcou.courtname,
(SELECT COUNT(*)
FROM tblcasetrafficticketlink
WHERE caseid = tc.caseid) AS ticketcount,
Max(tt.violationdate) AS violationdate,
( tt.address1
|| ','
|| tt.address2 ) AS address,
tt.city,
tt.state,
tt.zip,
tt.dob,
tt.sex
FROM tblcase tc
LEFT OUTER JOIN tblcasetrafficticketlink tcttl
ON tc.caseid = tcttl.caseid
LEFT OUTER JOIN tbltraffictickets tt
ON tcttl.courtid = tt.courtcode
AND tt.ticketnumber = tcttl.ticketnumber
AND ( tcttl.ticketextension = tt.ticketnumberex
OR tt.ticketnumberex IS NULL )
LEFT OUTER JOIN tblcourts tcou
ON tcou.courtid = tt.courtcode
WHERE tc.casetype = 'TRAFFIC'
AND tc.caseid<='"+recent_min_caseID+"'
GROUP BY tc.caseid,
tt.firstname,
tt.lastname,
tt.dob,
tt.sex,
tt.courtcode,
tcou.courtname,
tt.city,
tt.state,
tt.zip,
tc.casestatus,
tt.address1,
tt.address2
ORDER BY tc.caseid DESC
LIMIT 100;
this is taking much time to get data. can anybody help to improve performance.Here PRAGMA is useful? if so how? if not, tell me the way to fix this issue.
I've found that SQLite on Android seems to have some... unexpected quirks. In my case, it turned out that doing a straight query like select * from Foo where Bar is null was MUCH slower than selecting only the IDs and then fetching each row by ID individually. YMMV.

Categories

Resources