Multiple Joins in TSQL - sql-server

I am trying to JOIN multiple tables to the same value in a table. So I have the table ActivityPartyBase and it has a column PartyId. I want to join COntactId in ContactBase table to PartyId and AccountId in AccountBase table to PartyId. This is the code I am using and it doesn't return anything. If I only join one it works. Any ideas?
SELECT DISTINCT Appointment.ScheduledStart, ActivityPartyBase.ActivityId
, Appointment.ActivityId AS Expr1, ActivityPartyBase.ScheduledStart AS Expr2
, Appointment.Subject, ActivityPartyBase.PartyId, ContactBase.ContactId
, ContactBase.FullName
FROM Appointment
INNER JOIN ActivityPartyBase
ON Appointment.ActivityId = ActivityPartyBase.ActivityId
INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId
LEFT OUTER JOIN ContactBase ON ActivityPartyBase.PartyId = ContactBase.ContactId
ORDER BY Appointment.ScheduledStart DESC

Your inner joins are filtering out results because there is no corresponding record on the joined table. I've always found the easiest way to debug is to "Select *" and use all LEFT JOINs. This will show you everything in your tables that relates to your main table; you should be able to look at your data and figure out what table is missing a record easily at that point.
To confirm that this is just a naming convention mismatch,
INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId
Are PartyID and AccountId the PK/FK?

Given this...
FROM Appointment
INNER JOIN ActivityPartyBase ON Appointment.ActivityId = ActivityPartyBase.ActivityId
INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId
LEFT OUTER JOIN ContactBase ON ActivityPartyBase.PartyId = ContactBase.ContactId
... you state this works (?) ...
FROM Appointment
INNER JOIN ActivityPartyBase ON Appointment.ActivityId = ActivityPartyBase.ActivityId
/* INNER JOIN AccountBase ON ActivityPartyBase.PartyId = AccountBase.AccountId */
/* LEFT OUTER JOIN ContactBase ON ActivityPartyBase.PartyId = ContactBase.ContactId */
Since the LEFT OUTER JOIN won't explicitly cause no results, that won't be your problem. Since the INNER JOIN will cause what you're seeing, we can only deduce that the join condition is incorrect.
In other words, ActivityPartyBase.PartyId is not equal to AccountBase.AccountID.

Are you sure there is data in all three tables in the inner join?

I'm guessing one of your INNER JOINs isn't picking up any data. Start with all 3 joins, then take out one of the joins at a time see which one breaks it. Then look at your join conditions and see which column isn't returning a record.

SOunds to me as if the tables are mutually exclusive. If it is ione table it is not inthe other (poor design). Try left joins to both tables.

Related

How can I get 3 tables INNER JOIN in MS SQL Server

From the specialist table, retrieve the first name, last name and contact number for the people that provide care to penguins from the species table.
There are 3 tables: tbl_specialist, tbl_species, tbl_care
I need help trying to INNER JOIN the tables to display First, Last, And Contact for penguins.
SELECT specialist_fname, specialist_lname, specialist_contact
FROM ((tbl_specialist
INNER JOIN tbl_species ON species_care = tbl_species.species_care)
INNER JOIN tbl_care ON care_id = tbl_care.care_id)
WHERE species_name = 'penguin'
;
It's a bit difficult without seeing the exact schema of the tables, but your syntax for the subquery is a bit off and you need to alias columns that are found in multiple tables in a JOIN statment. Try rewriting your SQL like this:
SELECT spl.specialist_fname, spl.specialist_lname, spl.specialist_contact
FROM tbl_specialist spl
INNER JOIN tbl_species s
ON spl.species_care = s.species_care
INNER JOIN tbl_care c
ON s.care_id = c.care_id
WHERE s.species_name = 'penguin'
I'm obviously inferring which tables certain columns come from in the join, but hopefully you get the idea.
I figured it out thank you.
SELECT specialist_fname, specialist_lname, specialist_contact
FROM ((tbl_specialist
INNER JOIN tbl_care ON tbl_care.care_specialist = tbl_specialist.specialist_id)
INNER JOIN tbl_species ON tbl_species.species_care= tbl_care.care_id)
WHERE species_name = 'penguin'
;

SQLite join multiple values from two tables [duplicate]

Is there any difference (performance, best-practice, etc...) between putting a condition in the JOIN clause vs. the WHERE clause?
For example...
-- Condition in JOIN
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND CUS.FirstName = 'John'
-- Condition in WHERE
SELECT *
FROM dbo.Customers AS CUS
INNER JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE CUS.FirstName = 'John'
Which do you prefer (and perhaps why)?
The relational algebra allows interchangeability of the predicates in the WHERE clause and the INNER JOIN, so even INNER JOIN queries with WHERE clauses can have the predicates rearrranged by the optimizer so that they may already be excluded during the JOIN process.
I recommend you write the queries in the most readable way possible.
Sometimes this includes making the INNER JOIN relatively "incomplete" and putting some of the criteria in the WHERE simply to make the lists of filtering criteria more easily maintainable.
For example, instead of:
SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
ON ca.CustomerID = c.CustomerID
AND c.State = 'NY'
INNER JOIN Accounts a
ON ca.AccountID = a.AccountID
AND a.Status = 1
Write:
SELECT *
FROM Customers c
INNER JOIN CustomerAccounts ca
ON ca.CustomerID = c.CustomerID
INNER JOIN Accounts a
ON ca.AccountID = a.AccountID
WHERE c.State = 'NY'
AND a.Status = 1
But it depends, of course.
For inner joins I have not really noticed a difference (but as with all performance tuning, you need to check against your database under your conditions).
However where you put the condition makes a huge difference if you are using left or right joins. For instance consider these two queries:
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderDate >'20090515'
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'
The first will give you only those records that have an order dated later than May 15, 2009 thus converting the left join to an inner join.
The second will give those records plus any customers with no orders. The results set is very different depending on where you put the condition. (Select * is for example purposes only, of course you should not use this in production code.)
The exception to this is when you want to see only the records in one table but not the other. Then you use the where clause for the condition not the join.
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
WHERE ORD.OrderID is null
Most RDBMS products will optimize both queries identically. In "SQL Performance Tuning" by Peter Gulutzan and Trudy Pelzer, they tested multiple brands of RDBMS and found no performance difference.
I prefer to keep join conditions separate from query restriction conditions.
If you're using OUTER JOIN sometimes it's necessary to put conditions in the join clause.
WHERE will filter after the JOIN has occurred.
Filter on the JOIN to prevent rows from being added during the JOIN process.
I prefer the JOIN to join full tables/Views and then use the WHERE To introduce the predicate of the resulting set.
It feels syntactically cleaner.
I typically see performance increases when filtering on the join. Especially if you can join on indexed columns for both tables. You should be able to cut down on logical reads with most queries doing this too, which is, in a high volume environment, a much better performance indicator than execution time.
I'm always mildly amused when someone shows their SQL benchmarking and they've executed both versions of a sproc 50,000 times at midnight on the dev server and compare the average times.
Agree with 2nd most vote answer that it will make big difference when using LEFT JOIN or RIGHT JOIN. Actually, the two statements below are equivalent. So you can see that AND clause is doing a filter before JOIN while the WHERE clause is doing a filter after JOIN.
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN dbo.Orders AS ORD
ON CUS.CustomerID = ORD.CustomerID
AND ORD.OrderDate >'20090515'
SELECT *
FROM dbo.Customers AS CUS
LEFT JOIN (SELECT * FROM dbo.Orders WHERE OrderDate >'20090515') AS ORD
ON CUS.CustomerID = ORD.CustomerID
Joins are quicker in my opinion when you have a larger table. It really isn't that much of a difference though especially if you are dealing with a rather smaller table. When I first learned about joins, i was told that conditions in joins are just like where clause conditions and that i could use them interchangeably if the where clause was specific about which table to do the condition on.
Putting the condition in the join seems "semantically wrong" to me, as that's not what JOINs are "for". But that's very qualitative.
Additional problem: if you decide to switch from an inner join to, say, a right join, having the condition be inside the JOIN could lead to unexpected results.
It is better to add the condition in the Join. Performance is more important than readability. For large datasets, it matters.

Is the order of multiple INNER JOIN-s related with the tables relashionship?

I want to join some tables using INNER JOIN statement.Some of them have the many to many relashionship ,some one to many and some one to one. I want to know does the order of INNER JOIN-s statement matters and is it related with the type of relashionship(One to one,one to many etc.)? So does these three codes below output the same result?
SELECT ....
FROM table1
INNER JOIN (table2 INNER JOIN table3 ON table2.col=table3.col)
ON table1.col=table2.col
SELECT ....
FROM table1
INNER JOIN (table2 INNER JOIN table3 ON table2.col=table3.col)
ON table1.col=table3.col
SELECT ....
FROM table2
INNER JOIN (table1 INNER JOIN table3 ON table1.col=table3.col)
ON table3.col=table2.col
And can I replace the INNER JOIN of two tables with this code below?So does this code below represents the inner join of table 1 and table2?
SELECT ...
FROM table1,table2
WHERE (table1.col=table2.col)
Exactly order of joins is not matter.
Better to use
select ...
from table1
inner join table2 on table2.col=table1.col
inner join table3 on table3.col=table1.col
Yes, INNER JOIN's could be replaced with
WHERE t1.col=t2.col
And SQL plan will be the same.
But if there are other filters in where condition - will mix.
Also, if there is additional join conditions - better to filter out all not required records first.
It makes absolutely no difference to the results. Because you are using only inner joins, only the matches in all three tables will show.
If you were to use a LEFT OUTER join and an INNER join in one query, you could vary the resultsets.
For INNER JOIN it will give same result but with other type of join it will give different result.
for example:
SELECT ....
FROM table1
LEFT JOIN (table2 INNER JOIN table3 ON table2.col=table3.col)
ON table1.col=table2.col
above is equivalent to
SELECT ....
FROM table1
LEFT JOIN (
Select table2.col
From table2 INNER JOIN table3 ON table2.col=table3.col
) tbl
ON table1.col=tbl.col
First it will do INNER JOIN of table2 & table3 then the table1 will left joined with the result

Inner Join to Same Table Twice on same column

I'm having a problem with a SQL Server query trying to join a view with another view twice
SELECT
FAC.*
FROM
ViewFacturacionDiaria_Test AS FAC
INNER JOIN
ViewInformacionRepresentantes AS REP
ON REP.RepIDTabacal = FAC.Vendedor
INNER JOIN
ViewInformacionRepresentantes AS REP2
ON REP2.RepIDCtayOrden = FAC.Vendedor
WHERE
FecCpbte BETWEEN '2015-11-28' AND '2015-11-30'
In the "FAC" view I have sales information, in the other one I have a specific group of sales person which I want to filter from the main view.
I would like to understand why the query is returning an empty resultset.
Sorry, I cannot comment. But I believe Peter is right in his comment. Since you are using 2 inner joins they both need to return results. Are you expecting both joins to find a match?
Try this and see which column is null. That is the join that is resulting in no returned rows.
SELECT
FAC.Vendedor
,REP.RepIDTabacal
,REP2.RepIDCtayOrden
FROM
ViewFacturacionDiaria_Test AS FAC
LEFT JOIN
ViewInformacionRepresentantes AS REP ON
REP.RepIDTabacal = FAC.Vendedor
LEFT JOIN
ViewInformacionRepresentantes AS REP2 ON
REP2.RepIDCtayOrden = FAC.Vendedor
WHERE
FecCpbte BETWEEN '2015-11-28' AND '2015-11-30'

SQL Server speed: left outer join vs inner join

In theory, why would inner join work remarkably faster then left outer join given the fact that both queries return same result set. I had a query which would take long time to describe, but this is what I saw changing single join: left outer join - 6 sec, inner join - 0 sec (the rest of the query is the same). Result set: the same
Actually depending on the data, left outer join and inner join would not return the same results..most likely left outer join will have more result and again depends on the data..
I'd be worried if I changed a left join to an inner join and the results were not different. I would suspect that you have a condition on the left side of the table in the where clause effectively (and probably incorrectly) turning it into an inner join.
Something like:
select *
from table1 t1
left join table2 t2 on t1.myid = t2.myid
where t2.somefield = 'something'
Which is not the same thing as
select *
from table1 t1
left join table2 t2
on t1.myid = t2.myid and t2.somefield = 'something'
So first I would be worried that my query was incorrect to begin with, then I would worry about performance. An inner join is NOT a performance enhancement for a Left Join, they mean two different things and should return different results unless you have a table where there will always be a match for every record. In this case you change to an inner join because the other is incorrect not to improve performance.
My best guess as to the reason the left join takes longer is that it is joining to many more rows that then get filtered out by the where clause. But that is just a wild guess. To know you need to look at the Execution plans.

Resources