SQLITE query, concat data from another table without join - sqlite

I am trying to build an sqlite query against a database which I have no control over, i.e. I can't change the odd way data is currently stored.
My data is spread across several tables, and one in particular is causing me issues; contacts.
The tables I am interested in are structured as follows (examples just include what I care about);
Results
id
state
account
5
0
102
11
2
62
Data
id
results_id
type
date
contact_id
1
5
1033
1596664666
360
2
11
1034
1596452446
32
Contacts_list
id
contact_id
key
type
32
12
test
email
360
110
test2
email
360
5
test2
phone
Contacts
id
results_id
name
email
12
231
Test Account
test1#gmail.com
110
726
Test Account 2
test2#gmail.com
5
6
Test Account no
01234567890
So what I want to do is:
Query the data table to grab all the values in that table, lookup type from the relevant table.
join the results table (Data.results_id = Results.id) and lookup the relevant account and state details
Get the contacts name and email from the contacts table.
The last bit is what is throwing me. Data.contact_id = Contacts_list.id and then Contacts_list.contact_id = Contacts.id
If I do a left join on Contacts_list I get additional rows because Contacts_list can have multiple rows for the same ID and I just want as many rows as the Data table has. What I want is to get concat multiple contacts into a single cell, eg;
account
state
type
date
contact
102
0
1033
1596664666
Test Account (test1#gmail.com)
62
2
1034
1596452446
Test Account 2 (test2#gmail.com), Test Account no (01234567890)
I feel like there will be an easy solution, but I am scratching my head at the minute... Any ideas?

You must join all tables, group by data.id and use GROUP_CONCAT() to collect the contacts:
SELECT r.account, r.state, d.type, d.date,
GROUP_CONCAT(c.name || ' (' || c.email || ')') contact
FROM Data d
LEFT JOIN Contacts_list cl ON cl.id = d.contact_id
LEFT JOIN Contacts c ON c.id = cl.contact_id
LEFT JOIN Results r ON r.id = d.results_id
GROUP BY d.id
See the demo.

Related

Why does COUNT return NULL instead of `0` in this query?

I have the query
select d.did, count ( h.did ), unique_interested
from dealer as d
left outer join house as h
on h.did = d.did
left outer join (
-- cid = customer id
select hid, count (cid) as unique_interested
from is_interested
group by hid
) as ok
on h.hid = ok.hid
group by d.did
order by d.did asc
;
which is supposed to select the number of houses that each dealer is dealing, and the number of unique customers interested in said houses (as in the number of customers per dealer). This should happen even if the dealers have no houses to deal at the moment, which is why I'm using left outer joins when constructing the table the columns will be picked from.
Now, running this query against my database produces the following output:
d.did count ( h.did) unique_interested
----- -------------- ----------------
1 3
2 3 1
3 0
As you can see, instead of printing 0 in the last column, count returns null, when there is a null in one of the aparments produced by the last part of the join (as in cid is null):
select hid, count ( cid ) as unique_interested
from is_interested
group by hid
I know this is because there are apartments in the table produced by from, that no-one is interested in. But shouldn't count produce 0 instead of the actual column value null in every case?
Any explanation as to why this is happening would be appreciated, as it would lead me towards an answer to another question, which is "Why am I not getting the right number of unique interested customers per dealer from the table is_interested?", as with the current state of my database, the output should look more like:
d.did count ( h.did) unique_interested
----- -------------- ----------------
1 3 2
2 3 2
3 0 0

Updating Fields sequentially based on conditions

I have this current example data set
NEW_ID Name OLD_ID New_Name
123 Hello XYZ
124 How XYZ
125 Are XYZ
126 My ABC
127 Name ABC
128 Is ABC
129 Alex ABC
My objective is to amend the Name field to a new naming convention to be stored in New_Name- ie Hello_Part_1, How_Part_2, Are_Part_3 where all these records share an OLD_ID - in this case XYZ. Similarly, with My_Part_1, Name_Part_2, Is_Part_3, Alex_Part_4 etc with IDs that equal ABC.
I'm using SQL Lite with an Import of .CSV File.
The naming convention is as follows - NAME_PART_X where X increments on the number of records within that 'Group' of OLD_IDs.
SQL does not work sequentially; you have to express the operation independently for each row.
The number you want is the count of rows with the same old ID that also have a new ID that is the same or smaller as the new ID of the current row.
This can be computed with a correlated subquery:
UPDATE MyTable
SET New_Name = Name || '_Part_' ||
(SELECT COUNT(*)
FROM MyTable AS T2
WHERE T2.OLD_ID = MyTable.OLD_ID
AND T2.NEW_ID <= MyTable.NEW_ID);

Count two different columns values from the same table using SQLite Database table in android

I am trying to select multiple values from the same table. I need to select count values of the column rfid and process_status from the posts table and station_title from stations table.
Here are the two tables:
Posts table :
Id ownerId rfid stationId stationType process_status
1 107 rfid1 raj1222681607 like pending
2 107 rfid1 raj1222681607 like pending
3 107 rfid1 raj1125396157 like pending
4 107 rfid1 raj1222681607 like
5 107 rfid2 raj1222681607 like pending
6 107 rfid3 raj1222681607 like
Stations table :
Id title ownerId stationId stationLike stationPic
1 Check-in one 107 raj1125396157 1 0
2 nfc station 01 107 raj1222681607 1 0
From these two tables I want to fetch data as
Total RFIDs : 5
Total Pending : 3
Station Title : nfc station 01
The where clause conditions are : ownerId = 107 and the stationId = 'raj1222681607' and the process_status = 'pending'
So far I can achieve the total rfids, station title value; but i am not able to get the total pending value counting the process status.
My query snippet:
SELECT
COUNT(p.rfid) as TotalTap,
COUNT(p.process_status) as TotalPending,
s.title
FROM posts p
inner join
stations s
on p.stationId = s.stationId
WHERE
p.ownerId = 107 AND p.stationId = 'raj1222681607'
AND p.process_status = 'pending';
But this is giving the wrong output as :
Total RFIDs : 3 (THIS IS WRONG!!)
Total Pending : 3
Station Title : nfc station 01
To compute how many rows match a condition, use SUM over a boolean expression:
SELECT COUNT(*) AS TotalTap,
SUM(process_status = 'pending') AS TotalPending
FROM Posts
WHERE ownerId = 107
AND stationId = 'raj1222681607';
It does not really make sense to try to compute the third value in the same query; just use a separate, much simpler query:
SELECT title
FROM Stations
WHERE stationId = 'raj1222681607';
Android has a helper function for this:
String title = DatabaseUtils.stringForQuery(db,
"SELECT title FROM Stations WHERE stationId = ?",
new String[]{ "raj1222681607" });

How do I query to find if values in one table have any corresponding entries in other tables

I am trying to write a query that will check to see if values in one table have any corresponding entries in other tables. I have the following which works but is there a faster way? Maybe using exists() function?
For clarification, this will be in sqlite. Also, I need values for each row in Manufacturer and whether or not it has entries in any of the other tables.
select tM.val, min(t1.val) as MakesCars, min(t2.val) as MakesTrucks,
min(t3.val) as MakesVans from tableManufactures tM
left join tableCars t1 on tM.id = t1.Manid
left join tableTrucks t2 on tM.id = t2.Manid
left join tableVans t3 on tM.id = t3.Manid
group by tM.val
order by tM.val
Results would look something like this:
Manufacturer MakesCars MakesTrucks MakesVans
Ford 85 15 20
Chevy 72 12 NULL
Mazda 42 NULL NULL
So any value would indicate that they do make that and a null would indicate that they don't.
For the joins, the database has to look up all matching records, most of which are then dropped because of the min().
Using EXISTS indeed is likely to be more efficient:
SELECT val,
EXISTS (SELECT 1
FROM tableCars
WHERE Manid = tM.id) AS MakesCars,
EXISTS (SELECT 1
FROM tableTrucks
WHERE Manid = tM.id) AS MakesTrucks,
EXISTS (SELECT 1
FROM tableVans
WHERE Manid = tM.id) AS MakesVans
FROM tableManufactures AS tM
ORDER BY val

Filtering in Oracle based on a group of values contained in a list of values

I have following two tables:
ID_PERSON NAME
-----------------
1 John
2 Joe
3 Peter
ID_PERSON ID_SPECIALIZATION
------------------------------
1 5
1 6
1 7
2 5
2 1
3 6
3 10
I need to filter data based on group of ids ID_SPECIALIZATION that will be provided. For example
I want to display only those persons who has specialization in 5 and 6 so it will return only first person. In ASP.NET Web form there will be two listboxes, left and right button, in first LB there will be all possible specializations and user will choose some of them to second LB as filtering options. I have no idea how to put this filtering condition in sql query. Thanks for help.
You could use the following:
SQL> SELECT p.id_person, p.NAME
2 FROM person p
3 JOIN person_spe s ON p.id_person = s.id_person
4 WHERE id_specialization IN (5, 6)
5 GROUP BY p.id_person, p.NAME
6 HAVING COUNT(*) = 2;
ID_PERSON NAME
---------- -----
1 John
One way to do it:
SELECT
ID_PERSON
, NAME
FROM
Person AS p
WHERE EXISTS
( SELECT *
FROM
PersonSpecialization AS ps
WHERE ps.ID_PERSON = p.ID_PERSON
AND ps.ID_SPECIALIZATION = 5
)
AND EXISTS
( SELECT *
FROM
PersonSpecialization AS ps
WHERE ps.ID_PERSON = p.ID_PERSON
AND ps.ID_SPECIALIZATION = 6
)
SELECT d1.id_person, d1.name FROM tbl_table1 d1
INNER JOIN tbl_table2 d1
ON d1.ID_PERSON=d2.ID_PERSON
WHERE ID_SPECILIZATION = ?
Theres the query but I'm not sure how asp.net works and passing in the value. It might be work looking up bind variables which allows you to use place holders in the sql which oracle then caches the query and just uses the values that you pass in at run tuime using EXECUTE IMMEDIATE.

Resources