JOIN Across 3 tables - sql

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).

Related

why I get different number of records when using LEFT JOIN

I need to join many to many relationship. In order to do that I am using
LEFT OUTER JOIN
(SELECT
SICCode, QuoteID
FROM
NetRate_Quote_Insur_Quote_Busin
WHERE
QuoteID IN
(SELECT DISTINCT QuoteID
FROM NetRate_Quote_Insur_Quote_Busin)) nr ON nr.QuoteID = tblQuotes.QuoteID
The goal is to bring the column SICCode. For that, I am using DISTINCT statement to make relationship many to one. But for some reason I got different number of records.
The last LEFT OUTER JOIN is the one that I am stuck with
Full query looks like this:
SELECT
MONTH(INV.EffectiveDate) AS Effective_Month,
tblQuotes.PolicyNumber,
YEAR(INV.EffectiveDate) AS Effective_Year,
INV.EffectiveDate,
INV.[InvoiceDate] as [Billed Date],
tblQuotes.ExpirationDate as [Policy Expiration Date],
INV.DueDate,
dbo.tblFin_InvoiceDetails.AmtBilled AS Written
FROM
tblClientOffices
INNER JOIN
tblInsureds (NOLOCK)
INNER JOIN
tblFin_Invoices INV
INNER JOIN
tblFin_InvoiceDetails ON INV.InvoiceNum = dbo.tblFin_InvoiceDetails.InvoiceNum
INNER JOIN
tblCompanyLines (NOLOCK) ON dbo.tblFin_InvoiceDetails.CompanyLineGuid = dbo.tblCompanyLines.CompanyLineGUID
INNER JOIN
lstLines (NOLOCK) ON dbo.tblCompanyLines.LineGUID = dbo.lstLines.LineGUID
AND dbo.tblCompanyLines.LineGUID = dbo.lstLines.LineGUID
INNER JOIN
tblProducerLocations (NOLOCK) ON INV.ProducerLocationGUID = tblProducerLocations.ProducerLocationGUID
ON tblInsureds.InsuredGUID = INV.InsuredGUID
INNER JOIN
tblQuotes (NOLOCK) ON INV.QuoteID = tblQuotes.QuoteID
AND INV.QuoteControlNum = tblQuotes.ControlNo
INNER JOIN
lstPolicyTypes (NOLOCK) ON tblQuotes.PolicyTypeID = lstPolicyTypes.PolicyTypeID
INNER JOIN
tblSubmissionGroup (NOLOCK) ON tblQuotes.SubmissionGroupGuid = tblSubmissionGroup.SubmissionGroupGUID
INNER JOIN
tblCompanyLocations (NOLOCK) ON tblQuotes.CompanyLocationGuid = tblCompanyLocations.CompanyLocationGUID
INNER JOIN
tblUsers (NOLOCK) ON INV.UnderwriterUserGUID = tblUsers.UserGUID
ON tblClientOffices.OfficeGUID = tblQuotes.IssuingLocationGuid
LEFT OUTER JOIN
tblUsers tblUsers_1 (NOLOCK) ON tblSubmissionGroup.InHouseProducerUserGuid = tblUsers_1.UserGUID
LEFT OUTER JOIN
(SELECT SICCode, QuoteID
FROM NetRate_Quote_Insur_Quote_Busin
WHERE QuoteID IN
(SELECT DISTINCT QuoteID
FROM NetRate_Quote_Insur_Quote_Busin)) nr ON nr.QuoteID = tblQuotes.QuoteID
WHERE
(tblInsureds.TestInsured = 0)
AND (INV.Failed = 0)
AND (tblFin_InvoiceDetails.ChargeType = 'p')
ORDER BY
YEAR(INV.EffectiveDate),
MONTH(INV.EffectiveDate),
lstLines.LineID
What would be the trick to bring Column SICCode and keep the same number of records?
I also tried to do this:
LEFT OUTER JOIN NetRate_Quote_Insur_Quote_Busin nr ON nr.QuoteID =
(
SELECT distinct QuoteID from NetRate_Quote_Insur_Quote_Busin
where QuoteID =tblQuotes.QuoteID
)
But it gives me more records than it should be
Also tried this one:
LEFT OUTER JOIN
( SELECT TOP 1 SICCode, QuoteID
FROM NetRate_Quote_Insur_Quote_Busin
WHERE QuoteID IN
(SELECT DISTINCT QuoteID
FROM NetRate_Quote_Insur_Quote_Busin)order by QuoteID desc ) nr ON nr.QuoteID = tblQuotes.QuoteID
But doesnt bring me any SICCode
DISTINCT will not change a many to many relationship to a many to one. It looks like your data has many SICCode values to one QuoteID which is why you getting higher record counts.
You could use a window function like Rank, but this is an arbitrary selection.
You could try to pivot/unpivot the SICCode column, but that would give you 1 column for each possible value, which would not work if you have a large number of unique values in the column.
A final option is to create a new table which has a QuoteID column and a SICCodes column, then populate it withSICCodes being a comma seperated list of the codes.
In conclusion, there is no easy way to change a many to many relationship to a many to one relationship unless you are willing to lose data or there are only a few values.

SQL Query between three tables, get data only from one table

I have these 3 tables:
product table
id
siteId
optionsSet table
id
productId
...
option table
id
optionsSetId
code
...
Question:
How can I make a SQL query to select all from option table by knowing these two: option.code and product.siteId ?
I know how to do a query with JOIN on two tables, but I am struggling with joining these three tables.
Something like
SELECT
*
FROM
option
WHERE
code = #code
AND optionsSetId IN
(SELECT
os.id
FROM
optionsSet os
JOIN product p ON os.productId = p.Id
WHERE
p.siteId = #siteId)
where #code is your code parameter and #siteId is your siteid parameter
to use inner joins you would have to join all 3 tables together and that would like
SELECT
DISTINCT o.*
FROM
option o
JOIN optionsSet os ON o.optionsSetId = os.Id
JOIN product p ON os.productId = p.Id
WHERE
o.code = #code
AND p.siteId = #site
if you notice that requires a DISTINCT to only get the data from option. It may be simpler and easier to understand but not very efficient.
another option that someone will probably say is way more awesome is using EXISTS
SELECT
o.*
FROM
OPTION o
WHERE
o.code = #code
AND EXISTS(
SELECT
1
FROM
optionsSet os
JOIN product p ON os.productId = p.Id
WHERE
o.optionSetId = os.Id
AND p.siteId = #siteId
)
I used EXISTS exclusively for a few years and the started working on databases with tables that had +100million records and IN was faster than EXISTS in some cases and identical in the others. Plus IN is less code.
SELECT * FROM option
LEFT JOIN product
ON option.code = product.siteId (+)
--(+) is a left outter join. This should include all of the values in option.code and all of the values in product that have the same siteId as values in option.
I'm unsure on how you want OptionSet to relate to the other 2 databases though?
if you want to include the third tables result you can just add another join on that table for the condition you want.

Joining multiples columns from more 5 tables

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.

Transact SQL JOIN

I have the following query:
SELECT MS.idReg, MS.dsMotivo, A.contrato FROM MS
INNER JOIN S
ON S.motivoSiniestro = MS.idReg
INNER JOIN C
ON C.n__contrat = S.n__contrat
INNER JOIN A
ON A.n__article = C.n__article
Table MS has only 12 records, the ones I need and others have many more entries.
My problem is that I only want the 12 records from MS and their contrato column but I'm getting much more that that. Have tried many combinations of INNER, OUTER, LEFT and RIGHT joins. Any help?
You get too many records because there are several A.contrato values for each row in the MS table. Sql server does not know which one of all the A.contrato values to take so it returns all of them. First you need to decide which one you want.
If any will do you can simply write your query like this:
SELECT MS.idReg, MS.dsMotivo, MAX(A.contrato)
FROM MS
INNER JOIN S
ON S.motivoSiniestro = MS.idReg
INNER JOIN C
ON C.n__contrat = S.n__contrat
INNER JOIN A
ON A.n__article = C.n__article
GROUP BY MS.idReg, MS.dsMotivo
Try this one -
SELECT MS.idReg, MS.dsMotivo, A.contrato
FROM dbo.MS
OUTER APPLY (
SELECT TOP 1 A.contrato
FROM dbo.S
JOIN dbo.C ON C.n__contrat = S.n__contrat
JOIN dbo.A ON A.n__article = C.n__article
WHERE S.motivoSiniestro = MS.idReg
) s

Joining multiple tables and getting multiple attributes from one of them

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.