SQL join To Fetch Mutiple Records - sql

I need to find the firstName and Email address from of all teachers and parents in a single query
Here is the structure of the table :
// Patients Table
ID guid parentID PatientName
1 234 1258 John
2 xyz 111 Paul
// Patient_teacher table
ID PatiendGuid teacherid
1 122 132
2 xyz 1424
3 245 1545
4 xyz 1222
// Members table
ID guid email fname
22 123 hello#xyz.com hello
111 xyz parentEmail#xyz.com parentName
1424 343 teacherEmail#xyz.com teacherName
1222 546 teacher2EMail#xyz.com teacher2Name
And Here is the required Result:
//Required Result
fname Email
parentName parentEmail#xyz.com
techerName teacherEmail#xyz.com
teacher2Name teacher2Email#xyz.com
The problem is when I tried to search using join I found a single row that contains parentID and TeacherID
Here is what I tried:
select Members.email,Members.fname
from Members
join Patients on Members.guid = Patients.guid
join Patient_Teacher on Patient_Teacher.patientguid = Patients.guid
where patients.guid = 'xyz'

Here is the Solution :
select Members.id, Members.email, Members.fname
from Patients
join Patient_Teacher on Patient_Teacher.patientguid = Patients.guid
join Members on (Patient_Teacher.teacherid = Members.id
or Patients.parent = Members.id)
where patients.guid = 'xyz'

Have you checked the following reasons?
1- You have a table named 'Patients_teacher' but in your solution, you're referring to it as 'Patient_teacher'.
2- In 'Patients_teacher' table, you have a column named 'patiendguid' but in your solution you're referring to it as 'patientguid'.

Related

How do I maintain manager at level 2 when no employees (level 1) assigned?

I have two tables to use for employee manager relationship. One table is employee id, and the other is the parent child link. I am joining the employee table multiple times along with the parent child link table, trying to create: Sr Mgr (Lvl 1), Mgr (Lvl 2), and Employee (Lvl 3) however I am running into an issue with Mgr who don't have employees assigned to them. There isnt a destination record with the mgrid as source.
How would I go about creating a null record and keeping the mgr at level 2 who doesnt have employeeid assigned to them?
Table Layout
EmpID table as Eid
EmpID
123
456
ParentChild Table as PC:
DestinationID (Child)
SourceID (Parent)
456
123
789
123
111
789
Joins
Select eid.empID (Level_3), pc.sourceid (level_2), pc2.sourceid (level_1)
From empid as eid
Left join parentchild as pc on eid.empID = pc.destinationID
Left Join empid as eid2 on pc.sourceId = eid2.empid
Left join parentchild as pc2 on eid2.empid = pc2.destinationID
Expected results:
Level_1
Level_2
Level_3
Null
456
123
111
789
123
The manager without employees only shows up at level 1 since they report to sr manager and not at level 2 with a level 1 null record.
Level_1
Level_2
Level_3
456
123
Null
111
789
123
With oracle (like Oracle 19c, etc) you'll need to make a few adjustments to your SQL syntax. We only needed to use the linkage table parentchild to obtain the detail you required.
Try this one:
SELECT pc2.destinationid level_1, pc.destinationid level_2, pc.sourceid Level_3
FROM parentchild pc
LEFT JOIN parentchild pc2 on pc2.sourceid = pc.destinationid
WHERE pc.sourceid = 123
;
Result:
+------+-----------+
| 1 | 2 | 3 |
+------+-----------+
| 111 | 789 | 123 |
| null | 456 | 123 |
+------+-----------+
Full working test case
Note: With recursion, we don't need to use explicit joins for each level of the tree and the depth doesn't need to be known. Oracle has two ways to do that:
WITH clause - Common Table Expression
CONNECT BY - Oracle specific syntax

Rewrite Oracle SQL Self Join Query

I have the below users and network information in a USER table. I would like to fetch all the Users for a given NetworkID.
ID Name Value Owner
1 UserID 123 111
2 NetworkID 567 111
3 FName ABC 111
4 LName BCD 111
5 UserID 234 222
6 NetworkID 567 222
7 FName DEF 222
8 LName EFG 222
9 UserID 345 333
10 NetworkID 567 333
11 FName GHI 333
12 LName HIJ 333
Below is the Self Join query, I have written to achieve the expected result set
select distinct U1.value NetworkID
, U2.value Users
from User U1
join User U2 on U2.owner = U1.owner and U2.name = 'UserID'
where U1.name = 'NetworkID' and U1.value = '567'
Expected Result
NetworkID Users
567 123
567 234
567 345
The volume of the table is very large and it is taking very long time to fetch the results using this self join. Based on the DB restrictions, I cannot make changes to the existing schema (adding Indexes). I need suggestion on how this query can be rewritten effectively to achieve same result set.
Your query is fine:
select U1.value as NetworkID, U2.value Users
from User U1 join
User U2
on U2.owner = U1.owner and U2.name = 'UserID'
where U1.name = 'NetworkID' and U1.value = '567';
For this query, you want indexes on (owner, name) and (name, value, owner).

SQL Joins stop working when table columns are defined

I am using sql to create a custom ODBC query into Excel.
I have 2 tables 'TBL_CONTACT' and 'TBL_ADDRESS' that I want to INNER JOIN on 'contactid', which is a column that exists in both.
This works fine if I select all columns, but stops working if I start defining the columns I want to show.
Working code:
SELECT * FROM "TBL_CONTACT" AS CONTACT
INNER JOIN (SELECT * FROM "TBL_ADDRESS" AS ADDRESS) ADDRESS
ON CONTACT.contactid = ADDRESS.contactid
Non-working code:
SELECT CONTACT.contactid, CONTACT.fullname FROM "TBL_CONTACT" AS CONTACT
INNER JOIN (SELECT * FROM "TBL_ADDRESS" AS ADDRESS) ADDRESS
ON CONTACT.contactid = ADDRESS.contactid
This only shows the 'contactid' and 'fullname' columns from 'TBL_CONTACT' and doesn't join anything from 'TBL_ADDRESS'.
EXAMPLE:
TBL_CONTACT
contactid firstname fullname
1001 John John Smith
1002 Tom Tom Adams
TBL_ADDRESS
contactid line1 line2 postcode
1001 3 Farm Ln Essex AB1 1BA
1002 1 Tim st Kent CN2 2NC
Desired result:
contactid fullname contactid2 line1 line2 postcode
1001 John Smith 1001 3 Farm Ln Essex AB1 1BA
1002 Tom Adams 1002 1 Tim st Kent CN2 2NC
1st code gives following result:
contactid firstname fullname contactid2 line1 line2 postcode
1001 John John Smith 1001 3 Farm Ln Essex AB1 1BA
1002 Tom Tom Adams 1002 1 Tim st Kent CN2 2NC
2nd code gives following result:
contactid fullname
1001 John Smith
1002 Tom Adams
I'm fairly new to SQL but am not sure what i'm doing wrong here. Any help would be greatly appreciated!
Joining a table results in the columns being available for your select. When you select all columns (with * like in your first code snippet) the columns of your joined table will be selected, too. However, when manually selecting columns, you have to define which columns you want from your joined table, too.
Let's say you want to have the 2 columns contactid and fullname from your Table TBL_CONTACT and all columns from the joined table TBL_ADDRESS:
SELECT `TBL_CONTACT`.`contactid`, `TBL_CONTACT`.`fullname`, `TBL_ADDRESS`.* FROM TBL_CONTACT
INNER JOIN TBL_ADDRESS
ON `TBL_CONTACT`.`contactid` = `TBL_ADDRESS`.`contactid`
Backticks are optional.
Alternatively, you could specify columns for the joined table, too.
Try this
//MySQL
SELECT TC.contactid,TC.fullname,TA.`address_table_column`
FROM TBL_CONTACT TC
INNER JOIN TBL_ADDRESS TA
ON TC.contactid = TA.contactid
//SQL Server
SELECT TC.contactid,TC.fullname,TA.[address_table_column]
FROM TBL_CONTACT TC
INNER JOIN TBL_ADDRESS TA
ON TC.contactid = TA.contactid
Wnen you have joined multiple tables and you select some field you must specify
to which table the field belongs .
Because like in your case the same field can be in both tables and then mysql does not know which one to fetch.
So just use the table prefix in your query and of course SELECT all the fields you want:
SELECT `TBL_CONTACT`.`contactid`,`TBL_CONTACT`.`fullname`,`TBL_ADDRESS`.`contactid` as contactid2,`TBL_ADDRESS`.`line1`,`TBL_ADDRESS`.`line2`,`TBL_ADDRESS`.`postcode` FROM `TBL_CONTACT`
INNER JOIN `TBL_ADDRESS`
ON `TBL_CONTACT`.`contactid` = `TBL_ADDRESS`.`contactid`
SELECT contact.*, ADDRESS.* FROM "TBL_CONTACT" contact INNER JOIN "TBL_ADDRESS" ADDRESS ON contact.contactid = ADDRESS.contactid;

Select Statement to return TaskID if column Exists in another table

I have two tables.
First table is called task the second table is named countries.
My task table
ID TaskID Country CustomerID
------------------------------------------
1 213 china 22
2 213 USA 24
3 213 china 26
4 214 Canada 28
Countries table
ID Country
---------------
1 USA
2 Japan
3 England
I need a select statement that returns all task ID's that doesnt have its country i the countries table.
In this case I would need to return TASKID: 214 because canada is not in the countries table. I would not get TASKID: 213 because USA is in the countries table.
Try this:
SELECT
TaskID
FROM
Task T LEFT OUTER JOIN Countries C ON (T.COUNTRY = C.COUNTRY)
GROUP BY
TaskID
HAVING
COUNT(C.ID) = 0
Try this,
select taskid
from task where taskid not in
(select taskid from task where country in
(select country from countries))
Try like this,
SELECT t.taskid
FROM task t
WHERE EXISTS (
SELECT 1
FROM countries
WHERE country = t.country
)

Several lines of information to a single line

I have information about customer's email address and phonenumber, but the data is stored in different tables which results in several rows per customer.
I have my main table with customerId etc. which I need to join with email and phonenumber. To do so I have a "translation" table with a communication_id which connects the tables.
For example
Main table:
CustomerID var1 var2 ...
123 1 7
The translation table which I need to use to connect the main table with the tables that includes email and phone look like this
CustomerID CommID
123 780
123 781
123 782
And the table with the email could look like this
commID email
780 a#a.com
and the table with the phone number could look like this
commID phone
781 88888
what I achieve if I left join the above 3 tables to my main table is
CustomerID var1 var2 email phone
123 1 7 a#a.com ?
123 1 7 ? 88888
123 1 7 ? ?
I understand why I get 3 rows, but what I want to achieve is a single row like this
CustomerID var1 var2 email phone
123 1 7 a#a.com 88888
Thank you
EDIT:
The join syntax is
sel * from maintable
left join Communication on maintable.CustomerID=Communication.CustomerID
left join email on email.commID=Communication.CommID
left join phone on phone.commID=Communication.CommID
To combine multiple rows into one you usually do a GROUP BY:
SELECT maintable.CustomerID, MAX(email), MAX(phone)
FROM maintable
LEFT JOIN Communication ON maintable.CustomerID=Communication.CustomerID
LEFT JOIN email ON email.commID=Communication.CommID
LEFT JOIN phone ON phone.commID=Communication.CommID
GROUP BY maintable.CustomerID