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]
Related
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
I am trying to get all the values from the first left table but when I use two left joins its restricting the values from first table.
I used the below query
SELECT P.person_id, TS.Task_Id, TS.skill
FROM Person P
LEFT JOIN Person_Skill PS ON P.person_id = PS.person_id
LEFT JOIN Task_Skill TS ON PS.Skill = TS.Skill
WHERE ts.task_id = 245
I need all the person id from person table.
Just move the condition on the left joined table from the where clause to the on clause of the join:
select p.person_id, ts.task_id, ts.skill
from person p
left join person_skill ps
on p.person_id = ps.person_id
left join task_skill ts
on ps.skill = ts.skill
and ts.task_id = 245 --> here
Rationale: conditions in the where clause are mandatory. If there is no match in ts, then condition ts.task_id = 245 cannot be satisfied, since ts.task_id is null.
Use the filter condition in a sub query instead of using it as a global filter outside. This should give you the output that you desire.
SELECT P.person_id,TS.Task_Id,TS.skill FROM Person P
LEFT JOIN Person_Skill PS
ON P.person_id=PS.person_id
LEFT JOIN
(Select * from Task_Skill where task_id = 245) TS
ON PS.Skill=TS.Skill;
how to create view of this query anyone help me please, i want create view of this but its show me error
Msg 4506, Level 16, State 1, Procedure ordersview, Line 3 Column names
in each view or function must be unique. Column name 'ID' in view or
function 'ordersview' is specified more than once.
CREATE VIEW ordersview
AS
Select * from UserClaimData cd
Inner join UserClaimDeductions ud on
ud.CLAIMID = cd.ID
Inner join UserClaimApproval ua on
ua.CLAIMID = cd.ID
inner join ClaimDataBreakdown cb on
cb.CLAIMID = cd.ID
inner join AppExpenseTypes ae on
ae.ID = cb.EXPENSETYPE
inner join AppNOWTypes an on
ae.ID = an.EXPENSETYPEID
inner join AppAreas aa on
aa.ID = cb.AREAID
inner join AppZones az on
cb.ZONEID = az.ID
inner join AppRegions ar on
ar.ID = cb.REGIONID
The answer to the question you've asked is to specifically reference elements from each table; for example:
CREATE VIEW ordersview
AS
Select cd.ID AS ID1, ua.ID as ID2, etc... from UserClaimData cd
Inner join UserClaimDeductions ud on
ud.CLAIMID = cd.ID
Inner join UserClaimApproval ua on
ua.CLAIMID = cd.ID
inner join ClaimDataBreakdown cb on
cb.CLAIMID = cd.ID
inner join AppExpenseTypes ae on
ae.ID = cb.EXPENSETYPE
inner join AppNOWTypes an on
ae.ID = an.EXPENSETYPEID
inner join AppAreas aa on
aa.ID = cb.AREAID
inner join AppZones az on
cb.ZONEID = az.ID
inner join AppRegions ar on
ar.ID = cb.REGIONID
I would, however, suggest that you don't put such a complex join inside a view. Consider the columns you want, and perhaps think about a stored procedure, or a table value function.
What part of the error message do you not understand?
You have select *, which brings together all columns from all tables. Just based on the join conditions, it is clear that most tables have an ID column, so there are multiple columns called ID. CLAIMID also seems quite popular.
In general, using select * is discouraged. However, it should not be used for views. A view should state the columns that it contains:
select cd.Id, . . .
Your view has more than one column with the same name, and this is causing the error.
AppRegions has a column called ID
AppAreas has a column called ID
UserClaimData has a column called ID
Change the Select * to specify the columns of the tables you want to have on the View table, and put a particularry name, or just don't put them.
You need to change the name of some columns in the view. Use AppAreas.ID as aaID
A view is like a virtual table, So you can't have the same name for 2(or more) columns.
So to avoid this, in your select Query instead of * provide the column names, and if there are 2 columns with the same name and you need them both in the view, give them different alias names.
Suppose you have ColumnA in TableA and TableB and you want them both in the view. Create view like this
CREATE VIEW vm_Sample
SELECT
A.COLUMNA COLUMNA_1,
B.COLUMNA COLUMNA_2
FROM TABLEA A INNER JOIN TABLE B
ON A.ID = B.ID
I am very new to SQL, so I apologize in advance if my query doesn't look perfect. I am trying to create a new table for this statement. I have 6 tables joined on the primary key. I tried Create table as (but it does not work). If anyone could please me, it would be greatly, greatly appreciated!
SELECT *
FROM DATABASE.Table1
INNER JOIN DATABASE.Table2
ON DATABASE.Table1.PrimaryKey = DATABASE.Table2.PrimaryKey
INNER JOIN DATABASE.Table3
ON DATABASE.Table1.PrimaryKey = DATABASE.Table3.PrimaryKey
INNER JOIN DATABASE.Table4
ON DATABASE.Table1.PrimaryKey = DATABASE.Table4.PrimaryKey
INNER JOIN DATABASE.Table5
ON DATABASE.Table1.PrimaryKey = DATABASE.Table5.PrimaryKey
INNER JOIN DATABASE.Table6
ON DATABASE.Table1.PrimaryKey = DATABASE.Table6.PrimaryKey
WHERE PrimaryKey = ‘1’
So you want one table with all the fields from each of the source tables, is that right? You can use a SELECT.... INTO:
SELECT [Field List] INTO MyNewConsolidatedTable
FROM DATABASE.Table1
INNER JOIN DATABASE.Table2
ON DATABASE.Table1.PrimaryKey = DATABASE.Table2.PrimaryKey
INNER JOIN DATABASE.Table3
ON DATABASE.Table1.PrimaryKey = DATABASE.Table3.PrimaryKey
INNER JOIN DATABASE.Table4
ON DATABASE.Table1.PrimaryKey = DATABASE.Table4.PrimaryKey
INNER JOIN DATABASE.Table5
ON DATABASE.Table1.PrimaryKey = DATABASE.Table5.PrimaryKey
INNER JOIN DATABASE.Table6
ON DATABASE.Table1.PrimaryKey = DATABASE.Table6.PrimaryKey
WHERE PrimaryKey = ‘1’
Note that you will need to replace [Field List] and enumerate all of the fields that you want in the new table, because otherwise you'll have 6 fields called PrimaryKey, which SQL won't allow.
I'm trying to join multiple tables together for building a report. The report lists a course, revisions made to it, and who requested, made and approved the revisions.
Under requested, made an approved, the values are employee numbers. I'm trying to join my innerjoined table above, with the Employee table so I can list the names (not just employee numbers) of those that requested, made and approved revisions.
This is what I have which I know is totally wrong.
SELECT *
FROM Courses
INNER JOIN CourseRevisions ON CourseRevisions.PELID = Courses.PELID
INNER JOIN CourseGroups ON CourseGroups.CourseGroupID = Courses.CourseGroupID
INNER JOIN [dbo].[OPG_Employees] ON OPG_Employees.EmployeeID = CourseRevisions.UpdatedBy
AND OPG_Employees.EmployeeID = CourseRevisions.ApprovedBy
AND OPG_Employees.EmployeeID = CourseRevisions.RequestedBy
This only returns a single result which just happens to have the same employee ID listed for all 3 (Requested, Approved and Updated)
How would i get it so I can get the table result for individual employees in each?
You have to join to the OPG_Employees table once for each field, i.e. 3 times in the example above. One INNER JOIN to it for UpdatedBy, one INNER JOIN for ApprovedBy, one INNER JOIN for RequestedBy.
Something like so:
SELECT *
FROM Courses
INNER JOIN CourseRevisions ON CourseRevisions.PELID = Courses.PELID
INNER JOIN CourseGroups ON CourseGroups.CourseGroupID = Courses.CourseGroupID
INNER JOIN [dbo].[OPG_Employees] empUpdatedBy ON empUpdatedBy.EmployeeID = CourseRevisions.UpdatedBy
INNER JOIN [dbo].[OPG_Employees] empApprovedBy ON empApprovedBy.EmployeeID = CourseRevisions.ApprovedBy
INNER JOIN [dbo].[OPG_Employees] empRequestedBy ON empRequestedBy.EmployeeID = CourseRevisions.RequestedBy
You need a separate join for each employee being referenced:
SELECT *
FROM Courses INNER JOIN
CourseRevisions
ON CourseRevisions.PELID = Courses.PELID INNER JOIN
CourseGroups
ON CourseGroups.CourseGroupID = Courses.CourseGroupID INNER JOIN
[dbo].[OPG_Employees] UpdateEmp
ON UpdateEmp.EmployeeID = CourseRevisions.UpdatedBy INNER JOIN
[dbo].[OPG_Employees] ApprovedEmp
on OPG_ApprovedEmp.EmployeeID = CourseRevisions.ApprovedBy INNER JOIN
[dbo].[OPG_Employees] RequestedEmp
on RequestedEmp.EmployeeID = CourseRevisions.RequestedBy
Your original formulation required that all three ids be exactly the same.