Full Outer Joins in MS Access - ms-access

My situation: I have a central PI table (patient information) which stores every single patient in the database. Then I have a few other tables (ex. vital signs, self report scores, etc.). The problem is, not every patient completes measures in every table. I.e., a patient might have an entry in the vital signs table but not in the self report table. How can I run a query where it shows me ALL patients in the PI table and their corresponding vitals and SR data if it exists instead of restricting the query to only show me patients that have records in ALL three of those tables?

I'm unclear why you want a FULL OUTER JOIN.
You have a PI table which includes a row for every patient. You have another table like SR data which contains the self-reported data for those patients. Assuming they have a common key ... perhaps patient_id ... a LEFT JOIN will give you a row for each patient regardless of whether there is any SR Data available for that patient:
SELECT *
FROM
[PI table] AS pi
LEFT OUTER JOIN [SR Data] AS sr
ON pi.patient_id = sr.patient_id;
Note Access will be happy with either LEFT OUTER JOIN or just LEFT JOIN there. OUTER is not needed, but Access won't object if you include it.
So I think you only need a LEFT JOIN. You would only need (the equivalent of) a FULL OUTER JOIN if the SR Data includes rows which don't match to any of the existing patients in the PI table and you want those unmatched rows included in the query result. But you didn't indicate that applies to your question, so I'm ruling it out unless you tell us otherwise.
You can LEFT JOIN another table to the first query ...
SELECT *
FROM
([PI table] AS pi
LEFT OUTER JOIN [SR Data] AS sr
ON pi.patient_id = sr.patient_id)
LEFT JOIN [Vital Signs] AS v
ON pi.patient_id = v.patient_id;
... and extend from there for additional tables as needed. If you use the Access query designer to set up your joins, it will add in parentheses correctly as the db engine demands for any query which includes more than one join.

Access (unfortunately) does not support OUTER JOIN. What it does is INNER, LEFT and RIGHT JOINS.
INNER JOIN - Gives you only the information common to two tables.
RIGHT JOIN - Gives all information that are common to the two table and information that are not matched form the table that is on the RIGHT to the JOIN statement.
LEFT JOIN - Gives all information that are common to the two table and information that are not matched form the table that is on the LEFT to the JOIN statement.
OUTER JOIN - is the UNION of RIGHT JOIN and LEFT JOIN.
So as expected, you just have to perform two Queries that perform a JOIN in both directions and then marry them using a UNION. This is a long process, but is the only way !
SELECT * FROM
(SELECT table1.FieldName1, table2.FieldName2
FROM table1 RIGHT JOIN table2 ON table1.ID = table2.ID
UNION
SELECT table1.FieldName1, table2.FieldName2
FROM table1 LEFT JOIN table2 ON table1.ID = table2.ID)

Related

Cursor expression in MySQL

How do I achieve the same as an Oracle cursor expression does in a MySQL database (version from 5.6 onwards)
below is a sample query of an Oracle cursor expression
SELECT department_name, CURSOR(SELECT salary, commission_pct
FROM employees e
WHERE e.department_id = d.department_id)
FROM departments d;
How can I achieve the same as this with a MySQL database?
if i execute this query on oracle below output i will be produced,
depart_name cursor result
MCA { < SALARY=20000 , COMMISSION_PCT=2 > , < SALARY=40000,COMMISSION_PCT=20> ,}
BE {< SALARY=20000,COMMISSION_PCT=2 >,}
I don't know what a CURSOR() does in oracle because I've never touched oracle, but I don't know if it would help you but I think you wanted to join like this:
SELECT d.department_name, e.salary, e.commission_pct.
FROM departments d
INNER JOIN employees e
ON (e.department_id = d.department_id);
I give you this link for more information on joints:
https://sql.sh/cours/jointures
and according to sql.sh:
There are several methods to associate 2 tables together. Here is the
list of the different techniques that are used:
INNER JOIN: internal join to return the records when the condition is true in both tables. This is one of the most common
joins.
CROSS JOIN: cross join to make the Cartesian product of 2 tables. In other words, allows to join each row of a table with each
row of a second table. Attention, the number of results is
generally very high.
LEFT JOIN (or LEFT OUTER JOIN): external join to return all the records of the left table (LEFT = left) even if the condition is not
checked in the other table.
RIGHT JOIN (or RIGHT OUTER JOIN): External join to return all records in the right-hand table (RIGHT = right) even if the condition
is not checked in the other table.
FULL JOIN (or FULL OUTER JOIN) : external join to return the results when the condition is true in at least one of the 2 tables.
SELF JOIN : allows to join a table with itself as if it were another table.
NATURAL JOIN : natural join between 2 tables if there is at least one column with the same name between the 2 SQL tables.
UNION JOIN: joint of union.
if you have any questions, I am available to answer them.

Left join issue with reference table

Im having a bit of difficulty with getting user information from one place to another.
There are 3 tables dbo.gr_usersource and dbo.gr_task and dbo.gr_user
In the dbo.gr_task table a column is filled with values that match entries in dbo.gr_usersource table that has another value that corresponds to the value in the dbo.gr_user table. You could call it a reference table between dbo.gr_task and dbo.gr_user tables.
My query looks like this;
select
dbo.gr_task.task_number
, dbo.gr_task.task_name
, dbo.gr_task.task_description
from dbo.gr_task
left join dbo.gr_user AS Handler
on dbo.gr_usersource.usersource_user = Handler.user_id
and dbo.gr_task.task_handler = dbo.gr.usersource.usersource.id
The last step would be to get the column user_name from table user when the join is working.
You have missed mediator table in your join so use as per below-
SELECT dbo.gr_task.task_number,dbo.gr_task.task_name, dbo.gr_task.task_description
FROM dbo.gr_task AS gt
LEFT JOIN dbo.gr_usersource gus ON gt.task_handler=gus.usersource.id
LEFT JOIN dbo.gr_user AS gu ON gus.usersource_user=gu.user_id;
Note: If you want only matching rows in all 3 tables then you should use normal join instead of left join.
This may work for you.
Note that there are no columns from your joined tables in your select list so left joins would have no impact on your result set.
Inner joins will filter your results set even if you bring back no columns, i.e., enforce the join condition to match rows in both tables.
SELECT
t.task_number
, t.task_name
, t.task_description
FROM dbo.gr_task t
INNER JOIN dbo.gr_usersource us
ON us.usersource.id = t.task_handler
INNER JOIN dbo.gr_user u
ON u.user_id = us.usersource_user

MySQL getting data from 3 tables which are connected by mapping tables

I have the following database example:
The example is pretty much self-explanatory: There are lessons held by teachers at defined time periods (time_start, time_end) each time period -> lesson connection has its own max_students number.
I know want to list all lessons with all information of the 3 tables (and the max_students). I would do it like that (I heard, that joining table like that is the fastest way):
SELECT * FROM lesson, teacher, time, teacher_has_lesson, time_has_lesson
WHERE lesson.lesson_id = teacher_has_lesson.lesson_lesson_id
AND teacher.teacher_id = teacher_has_lesson.teacher_teacher_id
AND lesson.lesson_id = time_has_lesson.lesson_lesson_id
AND time.time_id = time_has_lesson.time_time_id
1.) Is this a good solution if you just want to join 3 tables or are there better ones?
2.) This SQL call will get me only lessons, that have a teacher and a time. I also want to display lessons, that are in the database, but dont have a teacher or time yet. How can I do that?
There's an alternative way of writing this using join syntax. What you have is equivalent to an inner join, where you only see rows where there are matches:
select
*
from
lesson l
inner join
teacher_has_lesson tl
on l.lession_id = tl.lesson_lesson_id
inner join
teacher t
on tl.teacher_teacher_id = t.teacher_d
inner join
time_has_lesson tml
on l.lesson_id = tml.lesson_lesson_id
inner join
time tm
on tml.time_time_id = tm.time_ud
There's another type of join called outer join, where all the rows from one table are shown, and null values supplied if there are no matching values in the other table. It comes in two or three variants. left outer join shows all rows from the first table. right outer join shows all rows from the second table. full outer join shows all rows from both tables. So, for your second query you could use:
select
*
from
lesson l
left outer join
teacher_has_lesson tl
on l.lession_id = tl.lesson_lesson_id
left outer join
teacher t
on tl.teacher_teacher_id = t.teacher_d
left outer join
time_has_lesson tml
on l.lesson_id = tml.lesson_lesson_id
left outer join
time tm
on tml.time_time_id = tm.time_ud

SQL to show even null record

Below is my sql statement
SELECT a.purchase_id,
b.username,
a.purchase_packageid,
a.purchase_tradelimit,
a.purchase_pincode,
a.purchase_datetime,
c.packages_name ,
FROM purchase a,
accounts b,
packages c
WHERE a.purchase_userid=b.UserId
AND c.packages_id=a.purchase_packageid
Basically the issue is I got 3 tables
Accounts
Purchase
Packages
The main table is Purchase, inside the table there is purchase_userid , which I need to use it to get username from table accounts
So the problem now is I got rows where the purchase_userid is blank, because its blank, it won't draw its record as null.
The only record that show in this sql statement is only those with purchase_userid,
As the value for purchase_userid will be fill up later for my web app,
I still want to select rows without purchase_userid and those with purchase_userid
Thanks for helping !!
You need to use a left join to load all records in Purchase even when no matching records are found in Accounts.
SELECT a.purchase_id, b.username, a.purchase_packageid, a.purchase_tradelimit, a.purchase_pincode, a.purchase_datetime, c.packages_name
FROM purchase a LEFT JOIN accounts b
ON a.purchase_userid=b.UserId
JOIN packages c
ON c.packages_id=a.purchase_packageid
This post explains the different kinds of joins pretty well: What's the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN and FULL JOIN?
You're using the old-timey syntax for INNER JOINs between your tables, when what you need is LEFT JOIN operations. Try this:
SELECT a.purchase_id,
b.username,
a.purchase_packageid,
a.purchase_tradelimit,
a.purchase_pincode,
a.purchase_datetime,
c.packages_name
FROM purchase AS a
LEFT JOIN accounts AS b ON a.purchase_userid = b.UserId
LEFT JOIN packages AS c ON a.purchase_packageid = c.packages_id
This works better for you because the kind of JOIN you were using suppresses records from your a table when they weren't matched in your b or c table. This LEFT JOIN will leave the a table records in place, and put NULL values where you are calling for data from the other two.

How to create the inner query wtih 5 different tables mysql

Having 5 tables
Table a_dates = id,
Table b_types = id, a_date_id, c_type_id,
Table c_types = id, name,
Table d_profiles = id, name, profile_type
Table e_ps = id, a_date_id, d_profile_id
From a_dates Need to get b_types,...then from b_types needs c_types name,... Then compare c_types name with d_profiles name and get d_profiles id.... if equals then create a records in e_ps with a_date_id, d_profile_id.
Could any one please help me in getting the query from inner join.
I tried like, it is incomplete query
INSERT INTO e_ps(id,a_date_id,a_date_type,d_profile_id,c_id)
SELECT '',a.id,'A',dp.id,'67' FROM d_profiles dp
INNER JOIN a_dates a ON {HERE I NEED NAME MATCHING WITH c_types name} = dp.name and dp.profile_type = 'A'
INNER JOIN a_dates ON a.id = a_dates.id
LEFT OUTER JOIN e_ps eps ON eps.a_date_type = 'A' AND eps.a_date_id = a_dates.id
WHERE eps.a_date_id IS NULL
This seems to be a relatively simple JOIN:-
INSERT INTO e_ps(id, a_date_id, d_profile_id)
SELECT NULL, a_dates.id, d_profiles.id
FROM a_dates
INNER JOIN b_types ON a_dates.id = b_types.a_date_id
INNER JOIN c_types ON b.c_type_id = c.id
INNER JOIN d_profiles ON c_types.name = d_profiles.name
With joins there are several types, and I suspect you are getting confused. Briefly:-
With an INNER JOIN it looks for a match that is on BOTH tables. If no
match the no record is returned.
With a LEFT OUTER JOIN it takes a record from the table on the left
and looks for a match on the table on the right. If a match great,
but if not then it still brings a row back but the columns from the
table on the right just have values of NULL.
A RIGHT OUTER JOIN is very much the same, just with the tables
reversed (most people including me avoid using this as it has no
advantages most of the time but just makes things confusing).
With a FULL OUTER JOIN it gets the records from both side, whether
they match or not. If they match then the columns from both are
returned, if not matched then the columns from one are returned. Not
that MySQL does not support a FULL OUTER JOIN (although there are
ways to emulate it).
A CROSS JOIN joins every combination of 2 tables. These are used when
there is no common column to match on but you want all combinations.
For example if you wanted a table of all employees and all days of
the week for each employee you would cross join a table of days of
the week against a table of employees (then for useful data you might
LEFT OUTER JOIN a table of holidays to the result).