When we require to fetch details from multiple tables the JOIN caluse is there for the rescue. But in SQL Server there are various types of JOINs which will cater our requirement in different ways. So it’s very important to have a good understanding in these types of JOINs and their usage.
In SQL Server following types of JOINs available.
- INNER JOIN
- OUTER JOIN
- LEFT OUTER JOIN
- RIGHT OUTER JOIN
- FULL OUTER JOIN
- CROSS JOIN
- CROSS APPLY
- OUTER APPLY
To illustrate the aforementioned JOINs I will use the following sample tables:
- SalesRep
- SalesDetails
- RepRating
- Settings
--== Create Tables ==-- CREATE TABLE RepDetails( RepId INT ,RepName VARCHAR(30) ) CREATE TABLE SalesDetails( RepId INT ,SaleMonth VARCHAR(6) ,OrderNo VARCHAR(6) ,SaleValue MONEY ) CREATE TABLE RepRating( RepId INT ,Rate INT ,YearMonth VARCHAR(6) ) CREATE TABLE Settings( S_Id INT ,S_Desc VARCHAR(20) ,S_Value VARCHAR(20) ) --== Populate Sample Data ==-- INSERT INTO RepDetails ( [RepId] ,[RepName] ) VALUES (1,'Eugene Thomas') ,(2,'John Wheeler') ,(3,'Curtis Bailey') ,(4,'Jeffrey Garrett') ,(5,'Rosemarie Hubbard') INSERT INTO SalesDetails ( [RepId] ,[SaleMonth] ,[OrderNo] ,[SaleValue] ) VALUES (7,'201607','XpyDy3',839) ,(1,'201607','NR0RTp',496) ,(4,'201607','4552T4',299) ,(6,'201607','GKhkyC',877) ,(4,'201606','iyK65Z',291) ,(6,'201606','NFCszW',446) ,(7,'201606','D238bN',135) ,(1,'201607','bERDXk',304) ,(7,'201608','nykZqB',935) ,(4,'201608','R7ea5v',352) ,(6,'201606','VVjIdo',407) ,(7,'201608','vtLT4z',977) ,(2,'201608','xnHTnO',416) ,(1,'201606','jFAJIm',674) ,(6,'201606','0Q011m',480) INSERT INTO dbo.RepRating( RepId ,Rate ,YearMonth ) VALUES (1,1,'201608') ,(3,2,'201608') ,(4,1,'201609') ,(2,2,'201609') INSERT INTO dbo.Settings( S_Id ,S_Desc ,S_Value ) VALUES (1,'LedgerMonth','201609') ,(2,'TaxRate','10%')
**Note: During the illustraion I will refer the table which is followed by the ‘FROM’ clause as the ‘Left Table’ and the table which is follwed by the JOIN clause as the ‘Right Table’.
INNER JOIN / JOIN
When we join two or more tables using an INNER JOIN, it will only return us the results when records can only be found on both left and right tables which will satisfy the condition we supply.This can be illustrated using a venn diagram as follows:
SELECT * FROM dbo.RepDetails AS RD JOIN dbo.SalesDetails AS SD ON SD.RepId = RD.RepId
**Please note: We have sales reps having RepId’s 1,2,3,4, & 5. But in SalesDetails table we have sales details for RepId’s 1,2,4,6 &7. So when these tables are joined the RepId’s which resides on both tables, which are 1,2, and 4 will return the details, ultimately giving us the aforementioned result set.
LEFT OUTER JOIN / LEFT JOIN
In a LEFT OUTER JOIN, unlike the INNER JOIN, it will select all the records from the ‘Left’ table and based on the JOIN condition, it will select any matching records from the ‘Right’ table and return us the results. If there are no matching details on the ‘Right’ table, columns on related to those rows will return as ‘NULL’.This can be shown using a venn diagram as follows:
SELECT * FROM dbo.RepDetails AS RD LEFT JOIN dbo.SalesDetails AS SD ON SD.RepId = RD.RepId
RIGHT OUTER JOIN / RIGHT JOIN
In a RIGHT OUTER JOIN, it will select all records from the ‘Right’ table and based on the JOIN condition it will select any matching records from the left table and return. If there aren’t any matching records on the left table it will return a ‘NULL’ value.This can be shown using a venn diagram as follows:
SELECT * FROM dbo.SalesDetails AS SD RIGHT JOIN dbo.RepDetails AS RD ON SD.RepId = RD.RepId
FULL OUTER JOIN / FULL JOIN
FULL OUTER JOIN is kind of a mx of both LEFT & RIGHT OUTER JOINs. It will return all rows from both ‘Left’ and ‘Right’ tables based on the JOIN condition. When the details aren’t matched it will return a NULL value in those respective columns.This can be shown using a venn diagram as follows:
SELECT * FROM dbo.RepDetails AS RD FULL OUTER JOIN dbo.SalesDetails AS SD ON SD.RepId = RD.RepId
CROSS JOIN
CROSS JOIN will return a result set which the number of rows equal to rows in ‘Left’ table multiplied by the number of rows in ‘Right’ table. Usually this behaviour is present when there’s no condition provided in the WHERE condition. So each row in the left table is joined to each row in the right table. Usuually this behaviour is called ‘Cartisian Product’SELECT * FROM dbo.RepDetails AS RD CROSS JOIN dbo.Settings AS S
But when some condition is provided via the WHERE clause CROSS JOIN will behave like an INNER JOIN
SELECT * FROM dbo.RepDetails AS RD CROSS JOIN dbo.Settings AS S WHERE RD.RepId = S.S_Id
**Note: In a CROSS JOIN it’s not possible to refer to a value in the Left table along with the right table. Example following code will result in an error.
SELECT * FROM dbo.RepDetails AS RD CROSS JOIN (SELECT * FROM dbo.Settings AS S WHERE S.S_Id = RD.RepId ) AS ST
CROSS APPLY behaves like an INNER JOIN and OUTER APPLY behaves like an OUTER JOIN. But the main differnce in APPLY compared to the JOIN is that the right side of the APPLY operator can reference columns in the table which is on the left side. This is not possible in a JOIN.
For example, suppose we need to fetch sales rep details along with the maximum sale record which they have done. So the following query is not possible since it is returning an error due to the aforementioned reason.
SELECT * FROM dbo.RepDetails AS RD JOIN( SELECT TOP 1 * FROM dbo.SalesDetails AS SD WHERE RD.RepId = SD.RepId ORDER BY SD.SaleValue DESC ) AS SData ON 1=1It will result in an error:
Msg 4104, Level 16, State 1, Line 78
The multi-part identifier "RD.RepId" could not be bound.
The way to achieve this is by using an APPLY.
CROSS APPLY
Considering the above requirement, we can use a CROSS APPLY in order to achieve the aforementioned.SELECT * FROM dbo.RepDetails AS RD CROSS APPLY( SELECT TOP 1 * FROM dbo.SalesDetails AS SD WHERE RD.RepId = SD.RepId ORDER BY SD.SaleValue DESC ) AS SData
Noticed the above sample, you can see that it returned three records. But if you inspect closely, the SalesRep table consists with five Reps. But CROSS APPLY has only returned the maximum sales value if there’s a matching record in the table right side to the APPLY operator. (Similar to an INNER JOIN)
OUTER APPLY
Using OUTER APPLY we can achieved a similar result like CROSS APPLY, but the difference is that even though there aren’t any matching records in the table right side to the APPLY operator, still it will return all the rows from the left side table, will NULL values for the columns in the right side table. We will consider the same query what we used in the above example, but changing the APPLY to an OUTER APPLY.SELECT * FROM dbo.RepDetails AS RD OUTER APPLY( SELECT TOP 1 * FROM dbo.SalesDetails AS SD WHERE RD.RepId = SD.RepId ORDER BY SD.SaleValue DESC ) AS SData
There are other capabilities which is possible using the APPLY. The following article explains these capabilites really well: http://bradsruminations.blogspot.sg/2011/04/t-sql-tuesday-017-it-slices-it-dices-it.html
Hope this will help you to understand the JOIN and the APPLY operator in SQL Server and where it can be used precisely.
No comments:
Post a Comment