Joining multiples columns from more 5 tables - sql

I am trying to join setid(like a foreign key) which exist in all the tables in the query and also I am trying to join lecid which only exist in lec table and in parktable table as well as joining weekid in week and parktime table. I am also trying to join the roomid in rooms table and parktable table. All together setid is like a foreign key in all those tables. I am looking for a setid which is 48596.
I have tried:
select t.slotid, r.number1, t.weekid, t.duration, p.name as DEPName,
a.name FROM parktime t
JOIN rooms k ON t.setid = k.setid
JOIN week r ON t.setid = r.setid
JOIN structure w ON t.setid = w.setid
FULL OUTER JOIN LEC p
ON
t.LECID = p.LECID
FULL OUTER JOIN week r
ON t.weekid = r.weekid
FULL OUTER JOIN structure w
ON
r.number1 = w.number1
FULL OUTER JOIN rooms k
on
k.roomid = t.roomid
WHERE t.setid = '48596'
The problem is that this query takes too long to run and at the end of it, it doesn't come back with the result. TEMP error.
Is they a problem with the way I am joining it?

don't use join twice, as you have here:
FULL OUTER JOIN JOIN rooms k
If speed is your issue, you may want to put indexes on the cols that you are using to join and in the where clause: setid, number1, etc.

Related

Is it possible to have multiple joins between two tables in stored procedure?

I have two tables, "Booking" and "City". CityName field is primary key in City table and I have used it as foreign key for two columns "SourceCity" and "DestinationCity" in Booking table. I want to create a stored procedure to select all existing data from the Booking table for creating a view list, for which I have written the following.
SELECT [dbo].[Booking].[BookingID],
[dbo].[Booking].[CustomerName],
[dbo].[City].[CityName],
[dbo].[City].[CityName],
[dbo].[Booking].[StartingDate],
[dbo].[Booking].[EndingDate],
[dbo].[Car].[LicensePlateNumber],
[dbo].[Driver].[DriverName],
[dbo].[Booking].[AdvanceTaken],
[dbo].[Booking].[PendingPayment],
[dbo].[Booking].[TotalRent],
[dbo].[Booking].[BookingDate],
[dbo].[Booking].[IDProof]
FROM [dbo].[Booking]
**LEFT OUTER JOIN [dbo].[City]
ON [dbo].[Booking].[SourceCity] = [dbo].[City].[CityName]
AND [dbo].[Booking].[DestinationCity] = [dbo].[City].[CityName]**
LEFT OUTER JOIN [dbo].[Driver]
ON [dbo].[Driver].[DriverID] = [dbo].[Booking].[DriverAllotted]
LEFT OUTER JOIN [dbo].[Car]
ON [dbo].[Car].[CarID] = [dbo].[Booking].[CarAllotted]
ORDER BY [dbo].[Booking].[BookingID]
I am not sure if it is possible to do the following
LEFT OUTER JOIN [dbo].[City]
ON [dbo].[Booking].[SourceCity] = [dbo].[City].[CityName]
AND [dbo].[Booking].[DestinationCity] = [dbo].[City].[CityName]
I guess you need a different JOIN
FROM [dbo].[Booking] as booking
LEFT OUTER JOIN [dbo].[City] as source_city
ON booking.[SourceCity] = source_city.[CityName]
LEFT OUTER JOIN [dbo].[City] as destination_city
ON booking.[DestinationCity] = destination_city.[CityName]
....
Yes it is possible, you just need to use a different table alias. Beyond referencing the same table twice, table aliases can make your code look a lot cleaner, e.g.
SELECT b.CustomerName,
sc.CityName AS SourceCity,
dc.CityName AS DestinationCity,
b.StartingDate,
b.EndingDate,
c.LicensePlateNumber,
d.DriverName,
b.AdvanceTaken,
b.PendingPayment,
b.TotalRent,
b.BookingDate,
b.IDProof
FROM dbo.Booking AS b
LEFT OUTER JOIN dbo.City AS sc
ON sc.CityName= b.SourceCity
LEFT OUTER JOIN dbo.City AS dc -- Different Alias here
ON dc.CityName = b.DestinationCity
LEFT OUTER JOIN dbo.Driver AS d
ON d.DriverID = b.DriverAllotted
LEFT OUTER JOIN dbo.Car AS c
ON c.CarID = b.CarAllotted
ORDER BY
b.BookingID;
I appreciate that cleaner is somewhat subjective, but I would be astonished if anyone found this harder to read than your original query

Joining two different columns from one table to the same column in a different table?

I am working on a query that has fields called ios_app_id, android_app_id and app_id.
The app_id from downloads table can be either ios_app_id or android_app_id in the products table.
Is it correct that because of that I cannot just run a simple join of downloads and products table on on p.ios_app_id = d.app_id and then join again on on p.android_app_id = d.app_id? Would that cause an incorrect number of records?
select p.product_id, d.date, d.downloads,
from products p
inner join download d
on p.ios_app_id = d.app_id
UNION
select p.product_id, d.date, d.downloads
from products p
inner join download d
on p.android_app_id = d.app_id
I would try:
select p.product_id, d.date, d.downloads,
from products p
inner join downloads d
on p.ios_app_id = d.app_id
inner join downloads d
on p.android_app_id = d.app_id
Basically I am trying to understand why the union here is needed instead of just joining the two fields twice? Thank you
Just join twice:
select p.product_id,
coalesce(di.date, da.date),
coalesce(di.downloads, da.downloads)
from products p left join
downloads di
on p.ios_app_id = di.app_id left join
downloads da
on p.android_app_id = da.app_id;
This should be more efficient than your method with union. Basically, it attempts joining using the two ids. The coalesce() combines the results into a single column.
Remember that the purpose of an INNER JOIN is to get the values that exists on BOTH sets of data (lets called them table A and table B), using a specific column to join them. In your example, if you try to do the INNER JOIN twice, what would happen is that the first time you execute the INNER JOIN, the complete PRODUCTS table is your table A, and you obtain all the products that have downloaded the ios_app, but now (and this is the key part) this result becomes your new dataset, so it becomes your new table A for the next inner join. And thats the issue, cause what you would want is to join the whole table again, not just the result of the first join, but thats not how it works. This is why you need to use the UNION, cause you need to obtain your results independently and then add them.
An alternative would be to use LEFT JOIN, but you could get null values and duplicates -and its not too "clean"-. So, for your particular case, I think using UNION is much clearer and easier to understand.
If you do left join in first query it will work.
create table all_products as (select p.product_id, d.date, d.downloads,
from products p
left join downloads d
on p.ios_app_id = d.app_id)
select a.product_id, d.date, d.downloads from all_products a left join downloads d
on a.android_app_id = d.app_id inner join

Joining multiple tables to one table in sql

I have a rather complex (well for me) sql query happening and I am having trouble with some concepts.
I have the following sql on a webpage that i am building
SELECT
[dbo].[Enrolment].[_identity], [dbo].[Enrolment].CommencementDate,
[dbo].[Enrolment].CompletionDate, [dbo].[Enrolment].enrolmentDate,
[dbo].[Course].name coursename, [dbo].[Course].Identifier as QUALcode,
[dbo].[Person].givenName, [dbo].[Person].Surname,[dbo].[Employer].name as empname,
[dbo].[Employer].Address1,[dbo].[Employer].Suburb,[dbo].[Employer].Phone,
[dbo].[Employer].PostCode,[dbo].[EnrolmentStatus].name as enrolname,
[dbo].[Student].identifier,[dbo].[Student].person,[dbo].[Contact].person as CONTACTid
FROM
(((([dbo].[Enrolment]
LEFT JOIN
[dbo].[Course] ON [dbo].[Enrolment].course = [dbo].[Course].[_identity])
LEFT JOIN
[dbo].[Employer] ON [dbo].[Enrolment].employer = [dbo].[Employer].[_identity])
LEFT JOIN
[dbo].[EnrolmentStatus] ON [dbo].[Enrolment].status = [dbo].[EnrolmentStatus].[_identity])
LEFT JOIN
[dbo].[Student] ON [dbo].[Enrolment].student = [dbo].[Student].[_identity])
LEFT JOIN
[dbo].[Person] ON [dbo].[Student].person = [dbo].[Person].[_identity]
LEFT JOIN
[dbo].[Contact] ON [dbo].[Employer].[_identity] = [dbo].[Contact].employer
WHERE
(([dbo].[EnrolmentStatus].name) = 'training'
OR
([dbo].[EnrolmentStatus].name) = 'enrolled')
This is working fine but what I would like to do is join to the [dbo].[Person] table again but this time joining from another table so the code I effectively need to patch into the above statement is
LEFT JOIN
[dbo].[Trainer] ON [dbo].[Enrolment].Trainer = [dbo].[Trainer].[_identity])
LEFT JOIN
[dbo].[Person] ON [dbo].[Trainer].person = [dbo].[Person].[_identity]
I then need to be able to get from the person table the name of the student and the name of the trainer, so I need 2 records from the person table for every record from the Enrolment table, the fields I need from the person table are the same for both trainer and student in that I am trying to get the given name and surname for both.
Any help or pointers would be most appreciated.
You have to just use replace your from clause with this. You have to just first use the Trainer table join, then Person table, then use the AND keyword to use multiple mapping with single table
FROM (((([dbo].[Enrolment]
LEFT JOIN [dbo].[Course] ON [dbo].[Enrolment].course = [dbo].[Course].[_identity])
LEFT JOIN [dbo].[Employer] ON [dbo].[Enrolment].employer = [dbo].[Employer].[_identity])
LEFT JOIN [dbo].[EnrolmentStatus] ON [dbo].[Enrolment].status = [dbo].[EnrolmentStatus].[_identity])
LEFT JOIN [dbo].[Student] ON [dbo].[Enrolment].student = [dbo].[Student].[_identity])
LEFT JOIN [dbo].[Trainer] ON [dbo].[Enrolment].Trainer = [dbo].[Trainer].[_identity])
LEFT JOIN [dbo].[Person] ON [dbo].[Student].person = [dbo].[Person].[_identity]
AND [dbo].[Trainer].person = [dbo].[Person].[_identity]
LEFT JOIN [dbo].[Contact] ON [dbo].[Employer].[_identity] = [dbo].[Contact].employer
Use aliasing like this..
LEFT JOIN [dbo].[Trainer] ON [dbo].[Enrolment].Trainer = [dbo].[Trainer].[_identity])
LEFT JOIN [dbo].[Person] AS p ON [dbo].[Trainer].person = p.[_identity]
If I get your question right - what you are trying to do is to join the same table twice in your SQL. You have one table Person which has both student and trainer information and you want to see their details side by side in your result set. So you need to join Person once with Student and another time with Trainer
To do this - you will have to join Person table together. Give your tables an alias like the other answers have suggested. Then your FROM clause can look like this -
FROM (((([dbo].[Enrolment]
LEFT JOIN [dbo].[Course] ON [dbo].[Enrolment].course = [dbo].[Course].[_identity])
LEFT JOIN [dbo].[Employer] ON [dbo].[Enrolment].employer = [dbo].[Employer].[_identity])
LEFT JOIN [dbo].[EnrolmentStatus] ON [dbo].[Enrolment].status = [dbo].[EnrolmentStatus].[_identity])
LEFT JOIN [dbo].[Student] ON [dbo].[Enrolment].student = [dbo].[Student].[_identity])
LEFT JOIN [dbo].[Person] P1 ON [dbo].[Student].person = P1.[_identity]
LEFT JOIN [dbo].[Contact] ON [dbo].[Employer].[_identity] = [dbo].[Contact].employer
LEFT JOIN [dbo].[Trainer] ON [dbo].[Enrolment].Trainer = [dbo].[Trainer].[_identity])
LEFT JOIN [dbo].[Person] P2 ON [dbo].[Trainer].person = P2.[_identity]
....
....
Here P1 and P2 are two aliases for [Person]

Does SQL Server 2012 Lazy Join

I am working on an application that allows users to dynamically choose what they see. The list of columns and tables those belong to is huge. I'm working on building a dynamic query but I don't want to have to store all the join logic if I don't have too.
An example is I have a query that has LEFT JOINS for 10 tables but I only select and filter by one table. Is SQL Server 2012 Smart enough to not join on the other tables that are not needed?
I know Oracle's DBMS works like this but my company uses SQL Server 2012 so I'm stuck with that.
Example Query where the last 4 LEFT JOINS don't need to be performed:
SELECT [IncidentIncidentNumberModValue].[IncidentNumber]
,IncidentNumberModifierNotValue.[Value] AS IncidentNumberNotValue
,[Incident].[IncidentDate]
,[Incident].[ResponseNumber]
,[Incident].[PatientCareReportNumber]
,[IncidentType].[Value] AS IncidentType
,[SceneStreetAddressModValue].[StreetAddress2] AS IncidentAddress
,IncidentStreetAddressNotValue.[Value] AS IncidentAddressNotValue
,COUNT(*) OVER() AS TotalRecordCount
FROM [EmsEvent].[Incident]
LEFT JOIN [Resource].[IncidentType] ON [EmsEvent].[Incident].[IncidentType] = [Resource].[IncidentType].[IncidentTypeID]
LEFT JOIN [EmsEvent].[IncidentIncidentNumberModValue] ON [EmsEvent].[Incident].[IncidentID] = [EmsEvent].[IncidentIncidentNumberModValue].[IncidentID]
LEFT JOIN [GlobalResource].[IncidentNumberModifier] ON [EmsEvent].[IncidentIncidentNumberModValue].[NotValue] = [GlobalResource].[IncidentNumberModifier].[DataElementID]
LEFT JOIN [GlobalResource].[NotValue] IncidentNumberModifierNotValue ON [GlobalResource].[IncidentNumberModifier].[NotValueID] = IncidentNumberModifierNotValue.[NotValueID]
LEFT JOIN [EmsEvent].[Scene] ON [EmsEvent].[Scene].[IncidentID] = [EmsEvent].[Incident].[IncidentID]
LEFT JOIN [EmsEvent].[SceneStreetAddressModValue] ON [EmsEvent].[Scene].[SceneID] = [EmsEvent].[SceneStreetAddressModValue].[SceneID]
LEFT JOIN [GlobalResource].[IncidentStreetAddressModifier] ON [EmsEvent].[SceneStreetAddressModValue].[NotValue] = [GlobalResource].[IncidentStreetAddressModifier].[DataElementID]
LEFT JOIN [GlobalResource].[NotValue] IncidentStreetAddressNotValue ON [GlobalResource].[IncidentStreetAddressModifier].[NotValueID] = IncidentStreetAddressNotValue.[NotValueID]
LEFT JOIN [EmsEvent].[CustomConfig] on [EmsEvent].[Incident].[IncidentID] = [EmsEvent].[CustomConfig].[IncidentID]
LEFT JOIN [EmsEvent].[IncidentDisasterType] on [EmsEvent].[Incident].[IncidentID] = [EmsEvent].[IncidentDisasterType].[IncidentID]
LEFT JOIN [EmsEvent].[Response] on [EmsEvent].[Scene].[SceneID] = [EmsEvent].[Response].[SceneID]
LEFT JOIN [EmsEvent].[CrewMember] on [EmsEvent].[Response].[ResponseID] = [EmsEvent].[CrewMember].[ResponseInformationID]
WHERE [EmsEvent].[Incident].[DeletedStatus] = 0
AND [EmsEvent].[Incident].AgencyID = '607CEE05-276D-49A1-B6BF-FD606EFC2377'
ORDER BY [EmsEvent].[IncidentIncidentNumberModValue].[IncidentNumber] ASC
OFFSET 0 ROWS
FETCH NEXT 25 ROWS ONLY
OPTION(recompile)
It depends on what column in the left outer joined table you are using in the join.
If the column is a primary key or has a unique constraint the table will be excluded from the query plan if it is not referenced elsewhere in the query.
It does not look like your last four tables are joined on their respective primary key.
With tables like this:
create table Parent
(
ParentID int primary key
)
create table Child
(
ChildID int primary key,
ParentID int references Parent(ParentID)
)
This query will not use the table Parent.
select C.*
from Child as C
left outer join Parent as P
on P.ParentID = C.ParentID
But this query have to use the left outer joined Child table because it might add rows to the result if there are more than one hit on the foreign key.
select P.*
from Parent as P
left outer join Child as C
on P.ParentID = C.ParentID

JOIN Across 3 tables

I am trying to join together 3 tables and potentially retrieve data from any of the columns.
I have a product and a lifestyle and a 'mapping table' that essentially contains references between the 2.
I want to do it properly using joins - but it is proving troublesome. If i use 'WHEREs' it works.
Here it is
This returns more results than I expect - it is probably doing the right thing, just not what I want!
SELECT DISTINCT PROFDESC.*
FROM PROFDESC
INNER JOIN PRODUCT ON PRODFUND.PRODCD = PRODUCT.PRODCD
INNER JOIN PRODFUND ON PRODFUND.PDFDCODE = PROFDESC.PROFREF
WHERE PRODFUND.PDFDTYPE = 2
This works fine but doesn't 'join' the tables.
SELECT DISTINCT PROFDESC.*
FROM PROFDESC, Product, Prodfund
WHERE
PRODFUND.PRODCD = PRODUCT.PRODCD and
PRODFUND.PDFDCODE = PROFDESC.PROFREF
AND PRODFUND.PDFDTYPE = 2;
I believe my first one is literally joining A to B and B to C where as I want the connection to include A to C
any suggestions?
You just need to have the tables in the query previously defined. This should work fine.
SELECT DISTINCT PROFDESC.*
FROM PROFDESC
INNER JOIN PRODFUND ON PRODFUND.PDFDCODE = PROFDESC.PROFREF
INNER JOIN PRODUCT ON PRODFUND.PRODCD = PRODUCT.PRODCD
WHERE PRODFUND.PDFDTYPE = 2
You should use the correct order when joining
SELECT DISTINCT PROFDESC.*
FROM
PROFDESC
INNER JOIN PRODFUND
ON PROFDESC.PROFREF = PRODFUND.PDFDCODE
INNER JOIN PRODUCT
ON PRODFUND.PRODCD = PRODUCT.PRODCD
WHERE
PRODFUND.PDFDTYPE = 2
But why are you joining to PRODUCT? You are not referring to any columns of it. Does the join somehow narrow the result? If not, drop it:
SELECT DISTINCT PROFDESC.*
FROM
PROFDESC
INNER JOIN PRODFUND
ON PROFDESC.PROFREF = PRODFUND.PDFDCODE
WHERE
PRODFUND.PDFDTYPE = 2
Maybe the DISTINCT can be dropped then (depending on the cardinality of the join).