SQL SELECT foreign key rows that have no rows in child table - sql

I need the following code to still show rows from the AUTHOR table even if they aren't called from any rows in the ALLOCATION table. Currently, the code shows all ALLOCATION rows with the appropriate foreign key data. I need it so that all rows from the AUTHOR table show up, even if they have no corresponding ALLOCATION row.
SELECT authid,sname,fname,B.bid
FROM ALLOCATION A
INNER JOIN BOOK B
ON A.bid = B.bid
INNER JOIN AUTHOR U
ON A.authid = U.authid
ORDER BY authid;
That is, some of the rows in the AUTHOR table are the foreign key of 0 of the rows in the ALLOCATION table. I need them to show up as well in a SELECT. authid, sname and fname are columns of the AUTHOR table.

select authid,
sname,
fname,
B.bid
from AUTHOR U
left outer join ALLOCATION A on A.authid = U.authid
left outer join BOOK B on A.bid = B.bid
order by authid

You want to use something called an outer join.
Instead of INNER, say LEFT OUTER or RIGHT OUTER, depending on the direction.
What this does is if there is no corresponding record in the other table, the columns are filled with null.

Related

Find left table and right table when we join more than 2 tables?

Suppose I have three tables here one of them is a Country table second one is a city table and the third one is a customer table, and I am writing a query here like this
SELECT country.country_name_eng, city.city_name, customer.customer_name
FROM Country
LEFT JOIN city ON city.country_id = country.id
LEFT JOIN customer ON customer.city_id = city.id
I want to know here who is the left table of the customer table and who is the left table of the city table as well as who is the right table of the country table and who is the right table of the customer table
'Left' is always the table at the left of the JOIN keyword, no matter if left, right, inner or full outer join, analogously 'right'.
Left and right joins, though, have different semantics:
With a normal (inner) join a data row is only added if there's a matching entry in both tables, e.g. if you JOIN ON l.id = r.id then if l contains an id with value 7 a row for is only added if there's a matching id with value 7 in r as well (and vice versa).
A left (outer) join instead adds a row for id 7 in l even if there's no matching id in r – then the corresponding columns for table r are filled with nulls.
Analogously a right (outer) join, all entries of r are added with nulls for l's columns if no matching entry found.
A full outer join is a combination of left and right outer join, any entry of l and r is used with nulls on either side for the counter part if none exists.
In your concrete query you'd list all countries even if there don't exist any cities – and if they do exist, for each country all of them even if there don't exist any customers there. In the latter case the columns for the customer are all filled with null values, and if no city exists either, additionally all city columns.

How to perform an INNER JOIN on columns with the same name

I am essentially swapping out the contents of column "LocationId" in the User table with the contents of column "LocationId" in table ChaplainLocation.
I tried a few INNER JOIN statements but have run into issues when it comes to differentiating between the two columns. I also tried setting aliases to no avail.
SELECT a.LocationID FROM [User] AS table1a,
a.ChaplainId,
a.FullName,
b.LocationId FROM [ChaplainLocation] AS table2b,
b.ChaplainId
FROM table1 a
INNER JOIN table2 b
ON a.LocationId = b.LocationId'''
I know the above SQL is messy, but I am new to INNER JOIN. I need the LocationId from table ChaplainLocation to replace LocationId in the User table.
Your current syntax is slightly off. Table aliases belong next to table names, and those appear in the FROM and JOIN clauses.
SELECT
a.LocationID AS LocationID_a,
a.ChaplainId AS ChaplainId_a,
a.FullName,
b.LocationId AS LocationId_b,
b.ChaplainId AS ChaplainId_b
FROM [User] AS a
INNER JOIN [ChaplainLocation] AS b
ON a.LocationId = b.LocationId;
Note that there is nothing wrong with referring to more than one column bearing the same name, so long as you qualify that column reference with a table alias (or full table name) to distinguish it.

When would you INNER JOIN a LEFT JOINed table /

I came across below code today.
SELECT StaffGroup.*
FROM StaffGroup
LEFT OUTER JOIN StaffByGroup
ON StaffByGroup.StaffGroupId = StaffGroup.StaffGroupId
INNER JOIN StaffMember
ON StaffMember.StaffMemberId = StaffByGroup.StaffMemberId
WHERE StaffByGroup.StaffGroupId IS NULL
The main table StaffGroup is being LEFT JOINed with StaffByGroup table and then StaffByGroup table is being INNER JOINed with StaffMember table.
I thought the INNER JOIN is trying to filter out the records which exist in StaffGroup and StaffByGroup but do not exist in StaffMember.
But this is not how it is working. The query does not return any records.
Am I missing something in understanding the logic of the query ? Have you ever used INNER JOIN with a table which has been used with LEFT JOIN in earlier part of the query ?
Actually you are missing one concept:
The main table StaffGroup is being LEFT Joined with StaffByGroup table and then this creates a virtual table say VT1 with all records from StaffGroup and matching records from StaffByGroup based on your match/filter condition in ON predicate.Then not StaffByGroup table but this VT1 is being INNER Joined with StaffMember table based on match/filter condition in ON predicate.
So basically the inner join is trying to filter out those records from StaffGroup and hence StaffByGroup which do not have a StaffMemberId.
Adding your where condition adds a final filter like from the final virtual table created by all the above joins remove all such records which don't have a StaffGroupId which in turn might be removing all rows collected in VT1 as all of them will be having some value for StaffGroupId.
To get all records from StaffGroup which have no StaffGroupId along with details from StaffMember for all such records you can add condition in ON predicate as:
SELECT StaffGroup.*
FROM StaffGroup
LEFT OUTER JOIN StaffByGroup
ON StaffByGroup.StaffGroupId = StaffGroup.StaffGroupId and StaffByGroup.StaffGroupId IS NULL
INNER JOIN StaffMember
ON StaffMember.StaffMemberId = StaffByGroup.StaffMemberId
This query looks fundamentally flawed - I guess what was originally intended is
SELECT StaffGroup.*
FROM StaffGroup
LEFT OUTER JOIN
(SELECT * FROM StaffByGroup
INNER JOIN StaffMember
ON StaffMember.StaffMemberId = StaffByGroup.StaffMemberId) StaffByGroup
ON StaffByGroup.StaffGroupId = StaffGroup.StaffGroupId
WHERE StaffByGroup.StaffGroupId IS NULL
which returns all groups from StaffGroup that dont' have existing staffmembers assigned to them (the INNER JOIN with StaffMember filters out those rows from StaffByGroup that don't have a matching row in StaffMember - probably because there exists no foreign key between them)
You are getting 0 records because of your where clause
where StaffByGroup.StaffGroupId is null
The left join links all the records from tbl A which are contained in tbl B and since you have specified StaffGROUPID as your key and then looked for Nulls values in your key, its 100% clear that you will end up with no results

I want to retrieve data from 4 tables in SQL Server

I want to retrieve data from 4 tables. Patient table has id as PK which is the foreign key in other three tables ett, phar and ssc. Where a patient lie in only one category. i.e patient id pt1 exists in either of the 3 tables. now I want to retrieve patient info along with its associated category.
My query is:
SELECT *
FROM Patient p
INNER JOIN ETT t
ON p.Patient_ID = t.Patient_ID || INNER JOIN Pharmacological ph
ON p.Patient_ID = ph.Patient_ID
I used OR clause because I want only 1 inner join executing at one time. but its not giving me results, any suggestions??
....Patient table has ID as PK which is the foreign key in other three
tables name: ett, phar and ssc where a patient lie in only one
category. Example, patient id pt1 exists in either of the 3 tables.
Based on your statement, you can join all the tables in table Patient using LEFT JOIN since a record can only exist on one table. The query below uses COALESCE which returns the first non-null value with int the list.
The only thing you need is to manually specify the column names that you want to be shown on the list as shown below.
SELECT a.*,
COALESCE(t.colA, p.ColA, s.ColA) ColA,
COALESCE(t.colB, p.ColB, s.ColB) ColB,
COALESCE(t.colN, p.ColN, s.ColN) ColN
FROM Patient a
LEFT JOIN ETT t
ON a.Patient_ID = t.Patient_ID
LEFT JOIN Phar p
ON a.Patient_ID = p.Patient_ID
LEFT JOIN SSC s
ON a.Patient_ID = s.Patient_ID
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
For or - do not ise ||, use "or"
You cannot join with or, you need re-format your query.

sql server - how to modify values in a query statement?

I have a statement like this:
select lastname,firstname,email,floorid
from employee
where locationid=1
and (statusid=1 or statusid=3)
order by floorid,lastname,firstname,email
The problem is the column floorid. The result of this query is showing the id of the floors.
There is this table called floor (has like 30 rows), which has columns id and floornumber. The floorid (in above statement) values match the id of the table floor.
I want the above query to switch the floorid values into the associated values of the floornumber column in the floor table.
Can anyone show me how to do this please?
I am using Microsoft sql server 2008 r2.
I am new to sql and I need a clear and understandable method if possible.
select lastname,
firstname,
email,
floor.floornumber
from employee
inner join floor on floor.id = employee.floorid
where locationid = 1
and (statusid = 1 or statusid = 3)
order by floorid, lastname, firstname, email
You have to do a simple join where you check, if the floorid matches the id of your floor table. Then you use the floornumber of the table floor.
select a.lastname,a.firstname,a.email,b.floornumber
from employee a
join floor b on a.floorid = b.id
where a.locationid=1 and (a.statusid=1 or a.statusid=3)
order by a.floorid,a.lastname,a.firstname,a.email
You need to use a join.
This will join the two tables on a certain field.
This way you can SELECTcolumns from more than one table at the time.
When you join two tables you have to specify on which column you want to join them.
In your example, you'd have to do this:
from employee join floor on employee.floorid = floor.id
Since you are new to SQL you must know a few things. With the other enaswers you have on this question, people use aliases instead of repeating the table name.
from employee a join floor b
means that from now on the table employee will be known as a and the table floor as b. This is really usefull when you have a lot of joins to do.
Now let's say both table have a column name. In your select you have to say from which table you want to pick the column name. If you only write this
SELECT name from Employee a join floor b on a.id = b.id
the compiler won't understand from which table you want to get the column name. You would have to specify it like this :
SELECT Employee.name from Employee a join floor b on a.id = b.id or if you prefer with aliases :
SELECT a.name from Employee a join floor b on a.id = b.id
Finally there are many type of joins.
Inner join ( what you are using because simply typing Join will refer to an inner join.
Left outer join
Right outer join
Self join
...
To should refer to this article about joins to know how to use them correctly.
Hope this helps.