I am trying to join two tables on two different columns and I was wondering if following two techniques are equivalent, if yes which one is better performance wise?
JOIN with OR (Conditional JOIN)
SELECT *
FROM table1
JOIN TABLE2 ON table1.value = table2.HighValue
OR table1.value = table2.LowValue
Using self Join
SELECT *
FROM TABLE1
JOIN table2 t2 ON table1.value = t2.HighValue
JOIN table2 t3 ON table1.value = t3.LowValue
The two queries are not equivalent, the first is equivalent to
SELECT *
FROM table1
JOIN TABLE2 ON table1.value = table2.HighValue
UNION
SELECT *
FROM table1
JOIN TABLE2 ON table1.value = table2.LowValue
Related
I am relatively new to SQL and I have the following question. I have the following code:
Select * from table1
LEFT JOIN table2 ON table1.name = table2.name and table1.id = table2.id
LEFT JOIN (SELECT id FROM table2 GROUP BY id) newtable ON table1.id = newtable.id
As both left joins uses data from the same table, is it possible to combine the two joins into one? How would the filters work in this case?
If your goal just to join table2 based on distinct values, then you can use WHERE and GROUP BY:
Select
*
from table1 t1
LEFT JOIN table2 t2
ON t1.name = t2.name and t1.id = t2.id
WHERE t1 id in (SELECT s2.id FROM table2 s2 GROUP BY s2.id)
Query #1:
Select t1.*
From t1
Join t2 on t1.c1 = t2.c1
Query #2:
Select t1.*
from t1
join t3 on t1.c2 = t3.c2
I would like to combine the results of above 2 select queries and not get any duplicates. I am doing an UNION but it is taking forever to execute
select t1.*
from t1
where
exists (
select t2.c1
from t2
where
t2.c1 = t1.c1
)
or exists (
select t3.c2
from t3
where
t3.c2 = t1.c2
)
or, if you need values from t2 and/or t3:
select t1.*
from t1
left outer join t2 on
t2.c1 = t1.c1
left outer join t3 on
t3.c2 = t1.c2
where
t2.c1 is not null
or t3.c2 is not null
You can try each to see if you get acceptable performance (I don't think you will based on your UNION experience). If it is slow, you should consider putting a indexes on c1 and c2 in both tables, preferably primary keys on the t2 and t3 tables, and then a non-clustered index on each of c1 and c2 on t1.
Amount of time will depend on several aspects of your environment.
Another way to return t1.* would be:
select distinct t1.*
from t1 a
join t2 b
on a.c1 = b.c1
join t3 c
on a.c2 = c.c2
Distinct will sort in tempdb (takes time)
I would like to apply conditions on each inner join like below
select *
from table1 table
inner join table2 t on t.column= table.column where condition
inner join table3 tb on tb.column = table.column where condition
But error is thrown on second where condition
Incorrect syntax near the keyword 'inner'.
Very new to joins in SQL Server. Any help please?
You need to put WHERE clauses at the end of the statement, but you can do this in an inner join like this:
select * from table1 table
inner join table2 t on t.column= table.column
and t.someColumn = 'SomeValue' --Here you can join on a condition
inner join table3 tb on tb.column = t.column
where <condition>
--Or...
select * from table1 table
inner join table2 t on t.column= table.column
inner join table3 tb on tb.column = t.column
where
t.column = 'blah'
and tb.column = 'blah2'
With an inner join all the conditions apply to the complete recordset. So you can just put them all in the where clause
select *
from table1 table
inner join table2 t on t.column= table.column
inner join table3 tb on tb.column = table.column
where condition1 and condition2
But for instance when using a left join the conditions only apply to the join itself. So you can use the on clause like this
select *
from table1 table
left join table2 t on t.column = table.column AND condition1
left join table3 tb on tb.column = table.column AND condition2
If you're looking to keep your main query clean, you can use a CTE to logically filter your table, away from your main query:
;with Employees as
(
select * from People where PersonType = 'Employee'
)
select * from ParkingSpots ps
join Employees e on ps.PersonID = e.PersonID
What is the name of this type of join? I've looked all over! The query is inner-joining back-to-back and then specifying two ON clauses.
Bonus points: What is the benefit of joining this way?
SELECT
<some columns>
FROM
ProductTypes AS t0
INNER JOIN Table1 AS t1
INNER JOIN Table2 AS t2
ON t2.CodeId = t1.CodeId
AND t2.[Enabled] = 1
ON t1.ClassId = t0.ClassId
Still it will be INNER JOIN.
It will interpreted as
SELECT <some columns>
FROM producttypes AS t0
INNER JOIN table2 AS t2
ON t1.classid = t0.classid
INNER JOIN table1 AS t1
ON t2.codeid = t1.codeid
AND t2.[enabled] = 1
Compiler is smart enough to rearrange the JOIN order
Here is demo of what's happening internally. I have used my own table's with similar JOIN order
Your query JOIN order
SELECT
*
FROM
users AS t0
INNER JOIN products AS t1
INNER JOIN orders AS t2
ON t2.productid = t1.productid
AND t2.productid = 1
ON t2.uid = t0.uid
Execution Plan
The rearranged JOIN order
SELECT
*
FROM
users AS t0
INNER JOIN orders AS t2
ON t2.uid = t0.uid
INNER JOIN products AS t1
ON t2.productid = t1.productid
AND t2.productid = 1
Execution Plan
As you can see both has identical execution plan. So there wont be any difference
This is a form of doing nested joins. There's no purpose with all inner unless you want to do it for readability. It can be useful if you use left outer. Consider:
SELECT
<some columns>
FROM
ProductTypes AS t0
LEFT OUTER JOIN Table1 AS t1
INNER JOIN Table2 AS t2
ON t2.CodeId = t1.CodeId
AND t2.[Enabled] = 1
ON t1.ClassId = t0.ClassId
Now this does something. If you did it without putting the t1/t0 at the end the t1/t2 inner would basically negate the fact that t1/t0 is a left outer. So doing it this way lets you have t0 records with no t1 records (just like a normal left outer join), but will only show the t1 records that ALSO have a t2. The inner join is enforced at this lower level.
See also:
http://sqlity.net/en/1435/a-join-a-day-nested-joins/
SQL join format - nested inner joins
I have a SQL query like this:
SELECT *
FROM table1
INNER JOIN table2 ON table1.key = table2.key
INNER JOIN table3 ON table1.var = table3.var
INNER JOIN table4 ON table1.field = table4.field
but I only want to include the table3 join if a variable has a certain value (iMarket=250 and above)
I'm trying to get this sort of condition working:
SELECT *
FROM table1
INNER JOIN table2 ON table1.key = table2.key
CASE
WHEN iMarket > 250
THEN INNER JOIN table3 ON table1.var = table3.var
END
INNER JOIN table4 on table1.field = table4.field
This is pseudo-code but it approximates to what I'm trying to do. Nothing works. Is there an easier way of doing it? I want to exclude this join because it always fails if that variable is below a certain value. Thank you all!
As easy to include condition in join on clause:
SELECT * from table1
INNER JOIN table2 on table1.key=table2.key
INNER JOIN table3 on iMarket>250 and table1.var=table3.var
INNER JOIN table4 on table1.field=table4.field
Remember than you should use outer joins if you need all values from other tables despite the fact that they are no matches for table3, perhaps you are looking for this behavior:
SELECT * from table1
INNER JOIN table2 on table1.key=table2.key
INNER JOIN table4 on table1.field=table4.field
left outer join --<--
table3 on iMarket>250 and table1.var=table3.var