In my Are you ready for SQL Server 2012 or are you still partying like it is 1999? post, I wrote about how you should start using SQL Server 2005 and SQL Server 2008 functionality now in order to prepare for SQL Server 2012. I still see tons of code that is written in the pre 2005 style and people still keep using those functions, procs and statements even though SQL Server 2005 and 2008 have much better functionality.

Today we are going to take a look at joins. SQL Server supports the ANSI SQL-92 (new style) syntax and the ANSI-SQL-89 (old style) syntax. Let’s take a look at both for INNER, OUTER and CROSS joins. This post is not about JOIN fundamentals, the internet is full of those and I won’t go into too much detail here, this post is mostly about showing you the difference between new and old style syntax.

Before we start, create these two extremely simple tables

T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
CREATE TABLE Test1(id int)
go
 
INSERT Test1 VALUES(1)
INSERT Test1 VALUES(2)
INSERT Test1 VALUES(3)
INSERT Test1 VALUES(4)
INSERT Test1 VALUES(5)
 
 
CREATE TABLE Test2(id int)
go
 
INSERT Test2 VALUES(1)
INSERT Test2 VALUES(2)
INSERT Test2 VALUES(3)
INSERT Test2 VALUES(4)
INSERT Test2 VALUES(6)
CREATE TABLE Test1(id int)
go

INSERT Test1 VALUES(1)
INSERT Test1 VALUES(2)
INSERT Test1 VALUES(3)
INSERT Test1 VALUES(4)
INSERT Test1 VALUES(5)


CREATE TABLE Test2(id int)
go

INSERT Test2 VALUES(1)
INSERT Test2 VALUES(2)
INSERT Test2 VALUES(3)
INSERT Test2 VALUES(4)
INSERT Test2 VALUES(6)

As you can see, each table has one row that does not exists in the other table

The INNER JOIN

Here is how you do an INNER JOIN in the old style syntax

T-SQL
1
2
SELECT * FROM Test1 t1,Test2 t2
WHERE t1.id = t2.id 
SELECT * FROM Test1 t1,Test2 t2
WHERE t1.id = t2.id 

Here is how you do it with the new style syntax

T-SQL
1
2
3
SELECT * FROM Test1 t1
JOIN Test2 t2
ON t1.id = t2.id 
SELECT * FROM Test1 t1
JOIN Test2 t2
ON t1.id = t2.id 

Both will return the following results set

id	id
1	1
2	2
3	3
4	4

The danger with the old style syntax is that you can forget the WHERE clause, with the new style syntax you will get an error

T-SQL
1
2
SELECT * FROM Test1 t1
JOIN Test2 t2
SELECT * FROM Test1 t1
JOIN Test2 t2

Msg 102, Level 15, State 1, Line 2
Incorrect syntax near ‘t2’.

Now run this

T-SQL
1
SELECT * FROM Test1 t1,Test2 t2 
SELECT * FROM Test1 t1,Test2 t2 

Output

id	id
1	1
2	1
3	1
4	1
5	1
1	2
2	2
3	2
4	2
5	2
1	3
2	3
3	3
4	3
5	3
1	4
2	4
3	4
4	4
5	4
1	6
2	6
3	6
4	6
5	6

As you can see, that created a Cartesian Product or CROSS JOIN, in the next section we will take a look at that

The CROSS JOIN

A CROSS JOIN or Cartesian Product will take each row in one table and match that with all rows from the second table. The size of a Cartesian product result set is the number of rows in the first table multiplied by the number of rows in the second table, in our case it is 5 x 5 = 25 rows

Here is the old style syntax we saw before

T-SQL
1
SELECT * FROM Test1 t1,Test2 t2
SELECT * FROM Test1 t1,Test2 t2

Here is the new style syntax

T-SQL
1
2
SELECT * FROM Test1
CROSS JOIN Test2
SELECT * FROM Test1
CROSS JOIN Test2

Output

id	id
1	1
2	1
3	1
4	1
5	1
1	2
2	2
3	2
4	2
5	2
1	3
2	3
3	3
4	3
5	3
1	4
2	4
3	4
4	4
5	4
1	6
2	6
3	6
4	6
5	6

I like the new style syntax much better, your intentions are clear, I know by looking at the code that the developer wanted a CROSS JOIN, with the old style syntax you always wonder if somehow they forgot the WHERE clause

Here is another way to do a CROSS JOIN, you can use CROSS APPLY

T-SQL
1
2
SELECT * FROM Test1
CROSS APPLY Test2
SELECT * FROM Test1
CROSS APPLY Test2

I will cover CROSS APPLY and OUTER APPLY in another post

The OUTER JOIN

The OUTER JOIN will take all rows from one table and match all the rows from the other table, when there is no match a row with NULLS will be returned. Let’s take a look

T-SQL
1
2
3
SELECT * FROM Test1 t1
LEFT OUTER JOIN Test2 t2
ON t1.id = t2.id 
SELECT * FROM Test1 t1
LEFT OUTER JOIN Test2 t2
ON t1.id = t2.id 

Output

1	1
2	2
3	3
4	4
5	NULL

As you can see for id 5, there is no matching row in table Test2 so a NULL is returned

Here is what the old style syntax looks like, go ahead and run it

T-SQL
1
2
SELECT * FROM Test1 t1,Test2 t2
WHERE t1.id *= t2.id 
SELECT * FROM Test1 t1,Test2 t2
WHERE t1.id *= t2.id 

Msg 102, Level 15, State 1, Line 2
Incorrect syntax near ‘*=’.

That is right, this syntax is deprecated and you won’t be able to use it anymore, get in the habit of using the OUTER JOIN syntax. BTW OUTER is optional, you can just specify LEFT JOIN, the queries below are identical

T-SQL
1
2
3
4
5
6
7
8
SELECT * FROM Test1 t1
LEFT JOIN Test2 t2
ON t1.id = t2.id 
 
 
SELECT * FROM Test1 t1
LEFT OUTER JOIN Test2 t2
ON t1.id = t2.id 
SELECT * FROM Test1 t1
LEFT JOIN Test2 t2
ON t1.id = t2.id 


SELECT * FROM Test1 t1
LEFT OUTER JOIN Test2 t2
ON t1.id = t2.id 

The RIGHT JOIN is the same as the LEFT JOIN but reversed

T-SQL
1
2
3
SELECT * FROM Test1 t1
RIGHT JOIN Test2 t2
ON t1.id = t2.id 
SELECT * FROM Test1 t1
RIGHT JOIN Test2 t2
ON t1.id = t2.id 

id      id
1	1
2	2
3	3
4	4
NULL	6

This two queries will give the exact same output

T-SQL
1
2
3
4
5
6
7
SELECT t1.*,t2.* FROM Test1 t1
RIGHT JOIN Test2 t2
ON t1.id = t2.id 
 
SELECT t1.*,t2.*  FROM Test2 t2
LEFT JOIN Test1 t1
ON t1.id = t2.id 
SELECT t1.*,t2.* FROM Test1 t1
RIGHT JOIN Test2 t2
ON t1.id = t2.id 

SELECT t1.*,t2.*  FROM Test2 t2
LEFT JOIN Test1 t1
ON t1.id = t2.id 

As you can see if you use RIGHT instead of LEFT and flip the tables around, it is the same exact query

Just as with the LEFT JOIN, you can use the old style RIGHT JOIN syntax anymore

T-SQL
1
2
SELECT * FROM Test1 t1,Test2 t2
WHERE t1.id =* t2.id 
SELECT * FROM Test1 t1,Test2 t2
WHERE t1.id =* t2.id 

Msg 102, Level 15, State 1, Line 2
Incorrect syntax near ‘*’.

A FULL OUTER JOIN will do an OUTER JOIN on both tables, whatever doesn match in either table will get a NULL in the result

T-SQL
1
2
3
SELECT t1.*,t2.*  FROM Test2 t2
FULL OUTER JOIN Test1 t1
ON t1.id = t2.id 
SELECT t1.*,t2.*  FROM Test2 t2
FULL OUTER JOIN Test1 t1
ON t1.id = t2.id 

id	id
1	1
2	2
3	3
4	4
NULL	6
5	NULL

As you can see each column has one NULL for the row missing in the table.

Just as with LEFT and RIGHT JOINS, OUTER is optional, you can leave it out

T-SQL
1
2
3
SELECT t1.*,t2.*  FROM Test2 t2
FULL JOIN Test1 t1
ON t1.id = t2.id 
SELECT t1.*,t2.*  FROM Test2 t2
FULL JOIN Test1 t1
ON t1.id = t2.id 

That is it for today’s post, come back tomorrow for OUTER and CROSS APPLY