Use of CASE in a SQL query - sql-server

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

Related

Conditional JOIN vs Self JOIN

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

replace nested where condition with join

I have a SQL query that looks like this
Select a.*
From table1 a
where a.ColumnName in
(Select MAX(b.ColumnName)
from table2 b
where b.ColumnName2 in
(
Select MAX(c.columnName)
from table3 c
Group by c.ColumnName2
)
Group by b.ColumnName2
)
I am trying to write this in a join statement. I am positive inner join is what I need to get the right information. If someone could translate this to a join statement, I would be really glad.
Thank you.
EDIT 1:
I tried the typical Join statement that a rookie would.
Select a.*
from table1 a
inner join table2 b
on a.columnname = (Select max(b.columnName) from table2)
inner join table3 c
on b.columnName = (select max(c.columnName) from table3)
Obviously, that didn't work because I get 100,000+ results when I should be getting 800. I tried using an alias for table2 and table3 INSIDE the subselect statements and selecting the columnname using THAT alias like this:
Select max(bPart.columnName from table2 bPart)
Select max(cPart.columnName from table3 cPart)
Still the same result.
PERHAPS....
Though I'm not sure why a join is needed. Performance wise exists would likely be fastest, and since you're not returning values from table2 or 3 it seems like it would be the best approach.
SELECT a.*
FROM table1 a
INNER JOIN (SELECT MAX(ColumnName) MColumnName, columnname2
FROM table2
GROUP BY columnName2) B
ON A.columnName = B.mColumnName
INNER JOIN (SELECT MAX(columnName) mColumnName
FROM table3
GROUP BY ColumnName2) C
ON B.columname2 = C.MColumnName

How to apply where condition in each inner join in SQL Server

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 type of SQL join is it in which the inner-join is not directly followed by an ON clause?

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

Difference between 'where' and 'And' in in line view query join

I had read in this thread below that there is no difference in the data returned in a query where you either have a Where predicate after the join or an 'And':
description of difference between 'where' and 'And' in join
However I do have different row counts in my query, which is using an in-line view query in my overall statement, when I change AND/WHERE. I have noticed that the issue is happening when I use a row number over statement in my in line query.
The reason I am using this is to restrict records in the in line query to only the first date record, so I can return subsequent but related records from the outer query.
However when I change the WHERE to an AND I get different number of rows.
My query is similar to this:
SELECT DISTINCT
table1.userID,
table2.UniqueID,
table3.entrydate,
table2.entrytime,
table4.changedatestart,
table2.changetimestart,
table5.changedateend,
table2.changetimeend,
table6.leavedate,
table2.leavetime,
table7.nationality_ID,
table8.reg_code
FROM
table1 INNER JOIN table2 ON (table1.t1_KEY=table2.t2_KEY)
RIGHT OUTER JOIN DATETIMETABLE table4 ON (change_start_date_alias.DATEKEY=table2.change_date_start_KEY)
RIGHT OUTER JOIN DATETIMETABLE table5 ON (change_end_date_alias.DATEKEY=table2.change_date_end_KEY)
RIGHT OUTER JOIN DATETIMETABLE table3 ON (entry_date_alias.DATEKEY=table2.ENTRY_DATE_KEY)
RIGHT OUTER JOIN DATETIMETABLE table6 ON (leave_date_alias.DATEKEY=table2.LEAVE_DATE_KEY)
RIGHT OUTER JOIN table7 ON (table7.nat_KEY=table2.nat_KEY)
INNER JOIN table8 ON (table8.reg_DEPT_KEY=table2.reg_DEPT_KEY)
RIGHT OUTER JOIN dbo.table9 ON (table9.leave_KEY=table2.leave_KEY)
INNER JOIN
(SELECT
table1.userID UID,
ROW_NUMBER() OVER (PARTITION BY table1.userID ORDER BY table3.entrydate ASC) as Seq,
table2.UniqueID "Unique_ID",
table3.entrydate "entry_date",
table2.entrytime "entry_time",
table4.changedatestart "change_start_Date",
table2.changetimestart "change Start Time",
table5.changedateend "change End Date",
table2.changetimeend "change End Time",
table6.leavedate "leave Date",
table2.leavetime "leave time",
table7.nationality_ID "Nationality ID",
table8.reg_code "Registration Code"
FROM
table1 INNER JOIN table2 ON (table1.t1_KEY=table2.t2_KEY)
RIGHT OUTER JOIN DATETIMETABLE table4 ON (change_start_date_alias.DATEKEY=table2.change_date_start_KEY)
RIGHT OUTER JOIN DATETIMETABLE table5 ON (change_end_date_alias.DATEKEY=table2.change_date_end_KEY)
RIGHT OUTER JOIN DATETIMETABLE table3 ON (entry_date_alias.DATEKEY=table2.ENTRY_DATE_KEY)
RIGHT OUTER JOIN DATETIMETABLE table6 ON (leave_date_alias.DATEKEY=table2.LEAVE_DATE_KEY)
RIGHT OUTER JOIN table7 ON (table7.nat_KEY=table2.nat_KEY)
INNER JOIN table8 ON (table8.reg_DEPT_KEY=table2.reg_DEPT_KEY)
RIGHT OUTER JOIN dbo.table9 ON (table9.leave_KEY=table2.leave_KEY)
WHERE table3.entrydate BETWEEN '20131201' AND '20140531'
AND table8.reg_DESC In ( 'Value1','Value2','Value3','Value4','Value5' )
AND table9.leave_CODE IN ('11','15','16','22','25','27','54','57','66')
)b
ON b.UID = table1.userID
**AND b.Unique_ID <> table2.UniqueID**
AND b.Seq = 1
AND b.[Registration Code] = table8.reg_code << If this line is commented out the same row count is returned whether WHERE/AND is used in not equal to ID statement:
AND/WHERE b.Unique_ID <> table2.UniqueID
But if I reintroduce the last lin and change the WHERE/AND used in the not equal to ID statement it gives slightly more rows when using the AND statement as opposed to the WHERE predicate.
In the original edit, you had inner join in example, thus I asked you to post the original code.
Please keep in mind, RIGHT OUTER JOIN is very very different from INNER JOIN in handling the ON clause. In a right outer join, you get all the records from the right table irrespective of the AND on the right table.
So, in the below query,
SELECT * FROM Table1 RIGHT OUTER JOIN Table2 ON Table1.ID = Table2.Id
AND TABLE2.ID = 2
you get all the records from Table2 even when you have put TABLE2.ID = 2. It just has no effect. Whereas, in the below query,
SELECT * FROM Table1 RIGHT OUTER JOIN Table2 ON Table1.ID = Table2.Id
WHERE TABLE2.ID = 2
You will get records only for TABLE2.ID = 2.
But for an inner join, both the below queries are similar:
SELECT * FROM Table1 INNER JOIN Table2 ON Table1.ID = Table2.Id
AND TABLE2.ID = 2
SELECT * FROM Table1 INNER JOIN Table2 ON Table1.ID = Table2.Id
WHERE TABLE2.ID = 2
So please handle AND conditions with care when you are not talking about RIGHT JOINS!
I had a similar question sometime back which I had asked here.

Resources