sql multiple attribute join - sql

I'm creating a test database on medical practices. Here is a picture of my er diagram for reference. ER diagram
So basically my question is how to do joins properly. I'm trying to give a list of patients seen from a given practice (e.g practice id 1) but i also want to show the practice name and details. I also want to show a list of the patients and and gp's who work or have been to that practice (keep in mind i have only populated my tables with 10 rows of test data)
I have got so far
select patient.firstname, patient.surname
from patient
Join appointment on patient.patientid = appointment.patientid
where appointment.practiceid IN (1)
ORDER BY firstname;
`How would i also include the practice details and the gp details also who are associated with this practice. What's confusing me is how i add more select statements if they are not from the patient table. Any help would be great!

You can just add more join clauses:
SELECT patient.firstname, patient.surname, practice.name, practice.address
FROM patient
JOIN appointment ON patient.patientid = appointment.patientid
JOIN practice ON appointment.practiceid = practice.practiceid
WHERE appointment.practiceid IN (1)
ORDER BY firstname;

I like aliasing my SQL statements. Saves on typing.
SELECT p.firstname, p.surname, pr.Details
FROM patient p
JOIN appointment a ON p.patientid = a.patientid
JOIN Practice pr ON pr.PracticeId = a.PracticeId
WHERE a.practiceid IN (1)
ORDER BY p.firstname;

I've included how to show the Practice_Name in your query, if you use the same join logic approach for each of the other queries you mention, you will work it out. I think that's a better way to learn rather than solving every question above in one answer.
SELECT PR.Practice_Name, P.firstname, P.surname
FROM patient AS P
INNER JOIN appointment AS A ON P.patientid = A.patientid
INNER JOIN Practice AS PR ON A.practiceid = PR.practiceid
WHERE A.practiceid IN (1)
ORDER BY P.firstname;

Related

SQL query wrong index when where on join

I have a query with joins that is not using the index that would be the best match and I am looking for help to correct this.
I have the following query:
select
equipment.name,purchaselines.description,contacts.name,vendors.accountNumber
from purchaselines
left join vendors on vendors.id = purchaselines.vendorId
left join contacts on contacts.id = vendors.contactId
left join equipment on equipment.id = purchaselines.equipmentId
where contacts.id = 12345
The table purchaselines has an index on the column vendorId, which is the proper index to use. When the query is run, I know the value of contacts.id which is joined to vendors.contactId which is joined to purchaselines.vendorId.
What is the proper way to run this query? Currently, no index is used on the table purchaselines.
If you are intending to query a specific contact, I would put THAT first since that is the primary basis. Additionally, you had left-joins to the other tables (vendors, contacts, equipment). So by having a WHERE clause to the CONTACTS table forces the equation to become an INNER JOIN, thus REQUIRING.
That said, I would try to rewrite the query as (also using aliases for simplified readability of longer table names)
select
equipment.name,
purchaselines.description,
contacts.name,
vendors.accountNumber
from
contacts c
join vendors v
on c.id = v.contactid
join purchaselines pl
on v.id = pl.vendorid
join equipment e
on pl.equipmentid = e.id
where
c.id = 12345
Also notice the indentation of the JOINs helps readability (IMO) to see how/where each table gets to the next in a more hierarchical manner. They are all regular inner JOIN context.
So, the customer ID will be the first / fastest, then to vendors by that contact ID which should optimize the join to that. Then, I would expect the purchase lines to have an index on vendorid optimizing that. And finally, the equipment table on ITs PK.
FEEDBACK Basic JOIN clarification.
JOIN is just the explicit statement of how two tables are related. By listing them left-side and right-side and the join condition showing on what relationship is between them is all.
Now, in your data example, each table is subsequently nested under the one prior. It is quite common though that one table may link to multiple other tables. For example an employee. A customer could have an ethnicity ID linking to an ethnicity lookup table, but also, a job position id also linking to a job position lookup table. That might look something like
select
e.name,
eth.ethnicity,
jp.jobPosition
from
employee e
join ethnicitiy eth
on e.ethnicityid = eth.id
join jobPosition jp
on e.jobPositionID = jp.id
Notice here that both ethnicity and jobPosition are at the same hierarchical level to the employee table scenario. If, for example, you wanted to further apply conditions that you only wanted certain types of employees, you can just add your logical additional conditions directly at the location of the join such as
join jobPosition jp
on e.jobPositionID = jp.id
AND jp.jobPosition = 'Manager'
This would get you a list of only those employees who are managers. You do not need to explictily add a WHERE condition if you already include it directly at the JOIN/ON criteria. This helps keeping the table-specific criteria at the join if you ever find yourself needing LEFT JOINs.

Trying to figure out a sql query to fetch the right data from multiple tables

So I have a database and I have 4 tables (admin, appointment, doctor, patient).
I only care about appointment, doctor and patient.
Diagram of these 3 tables:
What I want is based on a patients amka(int) to find all his appointments and show his name, surname and doctors name, surname.
I made this query:
(SELECT doctor.name, doctor.surname
FROM public.doctor
INNER JOIN public.appointment ON doctor.username = 'alouisot2')
union
(SELECT patient.name, patient.surname
FROM public.patient
INNER JOIN public.appointment ON patient.amka = '713783001');
The problem with this query is that it will only show appointments between this specific doctor and I just want to get all the doctors names and surnames.
Also I use postgresql.
I was trying to figure it out but I couldn't. I need to restructure the query but I cannot think how I would solve this problem.
If you have any idea on how to do achieve this I would really appreciate it.
Try this - properly join the three tables together (doctor to appointment based on the common username column, appointment to patient on the common amka column), and define the WHERE clause with your desired values:
SELECT
doctor.name, doctor.surname,
patient.name, patient.surname
FROM
public.doctor
INNER JOIN
public.appointment ON doctor.username = appointment.username
INNER JOIN
public.patient ON appointment.amka = patient.amka
WHERE
doctor.username = 'alouisot2'
AND patient.amka = '713783001';
this query just needs simple joins; you seem to have overcomplicated it a lot for some reason...
SELECT
patient.name,
patient.surname,
doctor.name,
doctor.surname
FROM public.patient
INNER JOIN public.appointment
ON patient.amka = appointment.amka
INNER JOIN public.doctor
ON appointment.username = doctor.username
WHERE patient.amka = '713783001'

On an SQL Select, how do i avoid getting 0 results if I want to query for optional data in another table?

I have a table with Customers which includes their contact person in the helpdesk. I have another table that lists all vacancies of the helpdesk employees - if they are currently sick or on vacation etc.
I need to get the helpdesk contact and the start/end time of their vacation IF there is an entry.
I currently have this (simplified):
SELECT *
FROM dbo.Customers, dbo.Projects, dbo.Vacations
WHERE ($Phone = dbo.Customers.Phone)
AND dbo.Customers.CustomerID = dbo.Projects.CustomerID
AND dbo.Projects.HDContactID = dbo.Vacations.HDContactID
So if there is a vacation listed in the Vacations table, it works fine, but if there is no vacation at all, this will not return anything - what i want is that if there is no vacation, it simply returns the other data, and ignores the missing data (returns NULL, doesn't return anything, not important)
In any case, I need to get the Customers and Project data, even if the query can't find an entry in the Vacations table. How would I do this? I pretty new to SQL and couldn't find a similar question on this site
EDIT: I'm using SQL Server, currently using HeidiSQL
Try below query:
SELECT * FROM dbo.Customers, dbo.Projects
left join dbo.Vacations on dbo.Projects.HDContactID = dbo.Vacations.HDContactID
WHERE ($Phone = dbo.Customers.Phone)
AND dbo.Customers.CustomerID = dbo.Projects.CustomerID
Use left join as mentioned by #Flying Thunder,
Example of the left join:
SELECT country.country_name_eng, city.city_name, customer.customer_name
FROM customer
LEFT JOIN city ON customer.city_id = city.id
LEFT JOIN country ON city.country_id = country.id;
You can find a nice guide for the joins and SQL here:
https://www.sqlshack.com/learn-sql-join-multiple-tables/
You should be using LEFT JOIN. In fact, you should never be using commas in the FROM clause. That is just archaic syntax and closes the powerful world of JOINs from your queries.
I also recommend using table aliases that are abbreviations of table names. The best are abbreviations for the table names:
SELECT *
FROM dbo.Customers c LEFT JOIN
dbo.Projects p
ON c.CustomerID = p.CustomerID LEFT JOIN
dbo.Vacations v
ON p.HDContactID = v.HDContactID
WHERE c.Phone = $Phone;
Have you try this to skip vacation record if not present like this:
SELECT * FROM dbo.Customers, dbo.Projects, dbo.Vacations
WHERE ($Phone = dbo.Customers.Phone)
AND dbo.Customers.CustomerID = dbo.Projects.CustomerID
AND (dbo.Vacations.HDContactID IS NULL OR dbo.Projects.HDContactID = dbo.Vacations.HDContactID)

Confused on the logic of multiple joins on multiple tables

I'm having a little problem with extracting and counting data from my database due to the way the database is setup.
Each case has multiple customers and suppliers with one main supplyer.
The main problems i need to over come are as follows:
To be able to first count the full amount of customers between a period of months driven by when the suppler jonied the company.
Count how many customers have had an "initial contact" as sometimes there will be no initial contact in the database.
I have tried to do this by using multiple joins in a single query but this doesn't seem to return complete data.
I'm so confused with using multiple joins, i understand that they can be executed in any order but i'm unsure what the second join is running on and also is i can legally join unrelated table in the same query or if i need to do a seperate query to do this.
Please find below a recreation of one of my many queries below with a very simplfied picture :
SELECT Count(cc.customercase)
FROM customer cc
LEFT JOIN customer
ON cc.custid = c.custid
LEFT JOIN maincase m
ON m.id = cc.caseid
LEFT JOIN custcontactlog cl
ON cl.caseid = cc.custcaseid
LEFT JOIN supcase sc
ON sc.caseid = m.id
WHERE cl.contactlogtype = 'Initial Contact'
AND sc.primarysupplyer = 1
AND Calctargetdate(sc.joindate) > cl.postdate
AND cl.postdate > sc.joindate
AND c.gender = 'M'
AND sc.joindate BETWEEN CONVERT(DATETIME, '01/01/2012', 103) AND
CONVERT(DATETIME, '31/03/2012', 103)
http://i50.tinypic.com/2qk3pqa.png
I will suggest that as you trying to achieve two things so you should have two separate queries to achieve it.

Query database not using stored procedure

i have a db diagram as shown above.
What I need to do is:
Select a table which is as follows:
PatientId, Emergency.Name or Doctor Names, Patient.Address.
Explanation; I need A query which will return patient details and, if Patient has an emergency also add an emergency, if not select all doctor.Name into one row.
So, example:
So, the first row was built because EmergencyId in table patient was null, while the second row had an emergency Id.
I need the query to simulate this. Using SSRS
Thanks a lot!
Thanks guys, can you at least explain
me how to return this data in separate
rows, so I can union later on?
I believe this will return the data you want broken out into separate rows, returning Emergency if it exists and the Drs if it does not. Good luck!
SELECT Distinct Coalesce(E.Name, D.Name) as VariableColumn,
P.PatientId,
P.Address
FROM Patient P
LEFT JOIN Emergency E
ON P.EmergencyId=E.EmergencyId
LEFT JOIN PatientDoctor PD
ON P.PatientID=PD.PatientId
LEFT JOIN Doctor D
ON PD.DoctorId=D.DoctorId
I can't really debug or work with your tables to check this, but here is a rough stab at something that should get you going:
SELECT P.PatientId, E.Name as 'EmergencyName', D.Name as 'DoctorName', P.Address
FROM Patient P
LEFT JOIN Emergency E ON P.EmergencyId=E.EmergencyId
LEFT JOIN PatientDoctor PD ON P.PatientID=PD.PatientId
LEFT JOIN Doctor D ON PD.DoctorId=D.DoctorId
ORDER BY P.PatientId, E.Name, D.Name, P.Address
Also, I'm no SQL Wizard. This should get the ball rolling, though.
Can you test this query against your data?
Does it return the desired results?
EDIT:
I just saw your comment about needing this layout with multiple values in one cell aligned vertically. That would require sub queries, and would be too much for me to write out.