SQL - Multi Table Joining with 1-1 and 1 - Many relationship - sql-server

I am trying to learn SQL and want to understand a scenario where i can Join 2 separate queries.
I have my APP_MTRX table would join with Cust Table to retrieve all the records whose TYPE_ORD_NUM = 0 or 1
I need to join ADD_DTLS Table with SHR_ADR table based on SHR_ADR_ID and need to retrieve all the columns whose adr_type_id is either 0 or 1 again
joining the result of 1 and 2
below is my SQL
select * from app_mtrx ABC
left join cust on cust.cust_id = ABC.cust_id and abc.cust_ty_ord = 0
left join cust BBC on cust.cust_id = BBC.cust_id and abc.cust_ty_ord = 1
left join add_dtls DEF ON DEF.cust_id=BBC.cust_id
left join shr_adr SHR on shr.shr_adr_id = def.shr_Adr_id
Can you please suggest if this is the correct approach and also if it is joining my 1 & 2 correctly....

Try this:
SELECT * FROM APP_MTRX am INNER JOIN Cust c
ON am.cust_id = c.cust_id
AND am.cust_ty_ord in (0,1)
INNER JOIN add_dtls ad
ON ad.cust_id=c.cust_id
INNER JOIN shr_adr sh
ON ad.shr_adr_id = sh.shr_Adr_id
AND ad.adr_type_id in (0,1)

Related

Filter a table using COUNT SQL Server

I am new to SQL. I have written the code below but am getting stuck with the COUNT function. I want to only display the ClientIDs that have 2 or more ServiceIDs on the Service table. I tried doing a nested select within the join on the Service table originally and was getting error messages. Now with the code below, I am getting an error
Msg 164, Level 15, State 1, Line 13
Each GROUP BY expression must contain at least one column that is not an outer reference.
I am trying to achieve the following. THANK YOU!
client Id
Service ID
Count
1
2
3
1
3
3
1
4
3
2
5
4
2
6
4
2
7
4
2
8
4
SELECT DISTINCT
O.OrgName,
Referral.ClientID,
Client.FirstName,
Client.LastName,
P.ProviderName AS 'School',
E.ProgramID,
LI.ListLabel AS 'Reason',
Race.ListLabel AS 'Race/Ethnicity',
Gender.ListLabel AS 'Sex/Gender',
[ServiceId],
(SELECT COUNT([ServiceID])
GROUP BY Referral.ClientID
HAVING COUNT([ServiceID]) >= 2) AS 'Number of Supports'
FROM
ProviderReferral Referral
JOIN
Provider P ON ReferFromProviderID = P.EntityID
JOIN
ProviderReferralExt ON Referral.ProviderReferralID = ProviderReferralExt.ProviderReferralID
INNER JOIN
MultiSelectValue MSV ON MSV.ContextID = Referral.ProviderReferralID
AND MSV.ContextTypeID = 87
AND MSV.ListID = 1000001179
INNER JOIN
Client ON Referral.ClientID = Client.EntityID
INNER JOIN
EnrollmentMember ON client.EntityID = EnrollmentMember.ClientID
INNER JOIN
Enrollment E ON EnrollmentMember.EnrollmentID = E.EnrollmentID
AND E.X_CMNonCM = 1
INNER JOIN
ListItem LI ON LI.ListValue = MSV.ListValue
AND LI.ListID = 1000001179
INNER JOIN
ListItem Race ON Race.ListValue = client.Race
AND Race.ListID = 1000000068
INNER JOIN
ListItem Gender ON Gender.ListValue = Client.Gender
AND Gender.ListID = 1
INNER JOIN
Service ON E.EnrollmentID = Service.EnrollmentID -- the supports table
JOIN
Organization O ON o.EntityID = p.OrganizationID
WHERE
P.OrganizationID = 33847
AND E.ProgramID = 1325
AND referral.DeletedDate = '9999-12-31'
AND o.DeletedDate = '9999-12-31'
AND enrollmentmember.DeletedDate = '9999-12-31'
ORDER BY
referral.ClientID, client.FirstName
You can use window function count as follows:
Select * from
(Select ...
...
Count([ServiceID]) over (partition by referral.clientid) as cnt
From ...
...
) t where cnt > 2;
Please note order by should be last clause in your query. Use it accordingly.
Based on the request in the comment, Adding the code into your original query as follows:
select * from
(select Referral.ClientID,
Client.FirstName,
Client.LastName,
P.ProviderName as School,
E.ProgramID,
LI.ListLabel as Reason,
Race.ListLabel as "Race/Ethnicity",
Gender.ListLabel as "Sex/Gender",
[ServiceId],
Count([ServiceID]) over (partition by referral.clientid) as cnt -- this -- added open parenthesis before partition
FROM ProviderReferral Referral
JOIN Provider P on ReferFromProviderID=P.EntityID
JOIN ProviderReferralExt on Referral.ProviderReferralID=ProviderReferralExt.ProviderReferralID
INNER JOIN MultiSelectValue MSV on MSV.ContextID = Referral.ProviderReferralID AND
MSV.ContextTypeID=87 AND MSV.ListID=1000001179
INNER JOIN Client on Referral.ClientID=Client.EntityID
INNER JOIN EnrollmentMember on client.EntityID=EnrollmentMember.ClientID
INNER JOIN Enrollment E on EnrollmentMember.EnrollmentID=E.EnrollmentID and E.X_CMNonCM=1
INNER JOIN ListItem LI on LI.ListValue = MSV.ListValue and LI.ListID = 1000001179
INNER JOIN ListItem Race on Race.ListValue=client.Race and Race.ListID=1000000068
INNER JOIN ListItem Gender on Gender.ListValue=Client.Gender and Gender.ListID=1
INNER JOIN Service on E.EnrollmentID=Service.EnrollmentID -- the supports table
JOIN Organization O on o.EntityID =p.OrganizationID
Where P.OrganizationID=33847
and E.ProgramID=1325
and referral.DeletedDate = '9999-12-31' and o.DeletedDate='9999-12-31'
and enrollmentmember.DeletedDate='9999-12-31') t
where cnt > 2 -- this
order by ClientID, FirstName

Join 4 tables and sum quantity for 2 tables using id from one table

My tables:
Order is:
PurchaseOrderHead
PurchaseOrder
ReceivingNoteHead
ReceivingNote
I want the output like this
MaterialID, PO.Quantity, RN.Quantity so far
There can be multiple receiving notes for a given purchaseorderhead_id as every ReceivingNoteHead will have a PurchaseOrderHeadID.
My attempt:
select
PurchaseOrder.MaterialID,
sum(distinct PurchaseOrder.Quantity) as "Sum_Quantity",
sum(ReceivingNote.Quantity) as "ReceivingNote_Quantity",
PurchaseOrderHead.id
from
(((dbo.PurchaseOrder
inner join
dbo.PurchaseOrderHead on (PurchaseOrderHead.id = PurchaseOrder.PurchaseOrderHeadID))
left outer join
dbo.ReceivingNoteHead ReceivingNoteHead (ReceivingNoteHead.PurchaseOrderHeadID = PurchaseOrderHead.id))
left outer join
dbo.ReceivingNote on (ReceivingNote.ReceivingNoteHeadID = ReceivingNoteHead.id))
group by
PurchaseOrder.MaterialID,
PurchaseOrderHead.id
having
(PurchaseOrderHead.id = 1004)
But ReceivingNote Quantities are repeated when there's no ReceivingNote MaterialID that matches PurchaseOrder's MaterialID.
This also does not work when theres multiple same MaterialID in either PurchaseOrder or ReceivingNote
I would like to learn whether I need to break the ReceivingNote table into 2 tables because of PurchaseOrderHeadID? And I want to get rid of the sum distinct because it's not the way I want it to be.
Maybe by first aggregating the material purchases in a sub-query.
Then left join that to the materials on the receiving end.
Untested notepad scribble:
SELECT
poMat.MaterialID,
poMat.TotQuantity AS [PurchaseOrder_Quantity],
SUM(rn.Quantity) AS [ReceivingNote_Quantity],
poMat.PurchaseOrderHeadID
FROM
(
SELECT
po.PurchaseOrderHeadID,
po.MaterialID,
SUM(po.Quantity) AS TotQuantity
FROM dbo.PurchaseOrder po
-- Uncomment to filter on the PurchaseOrderHeadID
-- WHERE po.PurchaseOrderHeadID = 1004
GROUP BY
po.PurchaseOrderHeadID,
po.MaterialID
) poMat
LEFT JOIN dbo.ReceivingNoteHead rnH
ON rnH.PurchaseOrderHeadID = poMat.PurchaseOrderHeadID
LEFT JOIN dbo.ReceivingNote rn
ON rn.ReceivingNoteHeadID = rnH.id
AND rn.MaterialID = poMat.MaterialID
GROUP BY
poMat.PurchaseOrderHeadID,
poMat.MaterialID,
poMat.TotQuantity
ORDER BY
poMat.PurchaseOrderHeadID,
poMat.MaterialID;
This however, won't show received materials that don't have a matching purchased material.
You are getting duplicate because the table ReceivingNoteHead does not have the PurchaseOrder.ID in it. Add the column PurchaseOrderID in ReceivingNoteHead and you should be good to go
select
PurchaseOrder.MaterialID,
sum(PurchaseOrder.Quantity) as "Sum_Quantity",
sum(ReceivingNote.Quantity) as "ReceivingNote_Quantity",
PurchaseOrderHead.id
from
dbo.PurchaseOrder
inner join
dbo.PurchaseOrderHead on PurchaseOrderHead.id = PurchaseOrder.PurchaseOrderHeadID
left outer join
dbo.ReceivingNoteHead ReceivingNoteHead ReceivingNoteHead.PurchaseOrderHeadID = PurchaseOrderHead.id *and ReceivingNoteHead.PurchaseOrderID=PurchaseOrder.ID*
left outer join
dbo.ReceivingNote on ReceivingNote.ReceivingNoteHeadID = ReceivingNoteHead.id
group by
PurchaseOrder.MaterialID,
PurchaseOrderHead.id
having
PurchaseOrderHead.id = 1004

sql server - How to Get all distinct value in group by column from two table and count from another table for each value

I have 3 tables in that 2 tables are master table and 3rd is transaction table. i need to get count from transaction table for each value in other two table without loosing rows in mater table
i need result like below
Table layout for understanding
This is the code i have tried,
select s.status_name, e.machine_group_name, qty = COALESCE(COUNT(e.id),0)
from tbl_status s
left outer JOIN tbl_transaction as e ON e.status_name = s.status_name
group by e.machine_group_name, s.status_name
This is solution i have figured:
select m.machine_group_name, s.status_name, qty = COUNT(e.id) from
tbl_machine_group as m
cross join tbl_status as s
left outer join tbl_transaction as e on e.status_name = s.status_name
and e.machine_group_name = m.machine_group_name
group by m.machine_group_name, s.status_name
order by machine_group_name
select
MC_Group_Name
,Status_Name
,count(1) as [Count of Transaction]
from
tbl_Transaction tbl_3
left join tbl_Machine_Group tbl_1
on tbl_3.MC_Group_Name = tbl_1.MC_Group_Name
left join tbl_Status tbl_2
on tbl_3.Status_Name = tbl_2.Status_Name
group by
MC_Group_Name
,Status_Name

Left join same table twice but one column is repeat

The main table want to join two time with the reffrence table twice with the same column.
The main table column is insert with integer and need to join with the refference table to get the character back to show back for user.
it show none of records by the sql below, why?
main table BD_BRAND
Sports_BR Leather_BR
2 1
Reffrence table BD_REF
ID NME REF_TYPE
1 NIKE Sports_Brand
2 ADIDAS Sports_Brand
3 PUMA Sports_Brand
1 CLACKS Leather_Brand
2 LOTTUSSE Leather_Brand
3 CHEANEY Leather_Brand
SELECT B.NME AS Sports_BR, C.NME AS Leather_BR
FROM BD_BRAND A
LEFT JOIN BD_REF B on B.ID = A.Sports_BR
LEFT JOIN BD_REF C on C.ID = A.Leather_BR
The Result i want as below:
Sports_BR Leather_BR
ADIDAS CLACKS
I think you're looking for:
SELECT B.NME AS Sports_BR, C.NME AS Leather_BR
FROM BD_BRAND A
LEFT JOIN BD_REF B on B.ID = A.Sports_BR and B.REF_TYPE = 'Sports_Brand'
LEFT JOIN BD_REF C on C.ID = A.Leather_BR and B.REF_TYPE = 'Leather_Brand'
Your ID's are present multiple times due to the different reference types, so you need to specify which ID to grab by the reference type.

SQL Server - Join across several tables

Below are the relevant tables info:
tgenie
Guid | genietypeguid | ...
and :
tgenieType
guid | genietype | ...
I made this query to select all possible entries:
select
tsearch.description,
tcompany.CompanyName,
tsearch.CompanyGUID,
tgenie.GenieNotes,
tGenieType.GenieType
from
tcompany, tsearch, tGenieType
left outer join
tGenie on tgenie.GenieTypeGUID = tGenieType.GUID
As the result I have this output:
description | CompanyName | CompanyGUID | GenieNotes | GenieType
VP Buiness AP Dev | Test | 5920B842-8216-45AA-A2AF-EA69740959FC | Test2 | Add'l Candidate Info
VP Buiness AP Dev | Test | 5920B842-8216-45AA-A2AF-EA69740959FC | Test3 | Add'l Candidate Info
VP Buiness AP Dev | Test | 5920B842-8216-45AA-A2AF-EA69740959FC | Test5 | Add'l Candidate Info
.
.
.
However, it does not work as supposed.
GenieType is set as "Add'l Candidate Info" for all the entries. I had ran the query for a long time and it seem to be the same for all the rows ... which does not seem right.
Any body has an idea why my join does not work?
Thanks in advance!
Update 1
I ended up with this query
It took 9 mins and has 1478028 rows...
select tsearch.Description,
tcompany.CompanyName,
tcompany.GUID as CompanyGuid,
tcompanylocation.LocationName,
tsearchtype.SearchType,
tsearchresult.searchresult,
tpeople.GUID as PersonPlacedGuid,
tpeople.LastName As PersonPlacedLName,
tpeople.Firstname As PersonPlacedFName,
tpeople.address1,
tpeople.address2,
tpeople.city,
tpeople.zipcode,
tpeople.city2,
tpeople.zipcode2,
tpeople.emailaddress,
tpeople.website,
tpeople.homephone,
tpeople.OtherPhoneDescription1,
tpeople.otherphone1,
tpeople.otherphonedescription3,
tpeople.otherphone3,
tpeople.resumefile,
tpeople.resumeocr,
tpeople.timeentered,
tPeopleEducation.education,
tPeopleEducation.GradYear,
tsearch.SearchNotes,
( select tpeople.Firstname from tpeople where tpeople.guid=tSearch.RepresentativeGUID) as repfirstname,
( select tpeople.Lastname from tpeople where tpeople.guid=tSearch.RepresentativeGUID) as replastname,
tsearch.RepresentativeGUID as RepGuid,
tposition.Position as backgroundposition,
tdepartment.Department as backgrounddepartment,
( select tpeople.Lastname from tpeople where tpeople.guid=tSearch.ReferredByGUID) as referredbylastname,
( select tpeople.FirstName from tpeople where tpeople.guid=tSearch.ReferredByGUID) as referredbylastname,
tsearch.ReferredByGUID as PersonwhorefferedGuid,
( select tcompany.CompanyName from tCompany where tCompany.guid=tSearch.PlacedFromGUID) as placedfrom,
tinstantstatustype.InstantStatus,
tWorkbench.WorkbenchName,
( select tpeople.Lastname from tpeople where tpeople.guid=tInstantStatus.PeopleGUID) as Candlastname,
( select tpeople.FirstName from tpeople where tpeople.guid=tInstantStatus.PeopleGUID) as candFirstname,
tInstantStatus.ForClientNotes,
tinstantstatus.InstantStatusNotes as InstanttatusNotesSummary,
tGenie.GenieNotes,
tGenieType.GenieType,
tgenielabel.GenieLabel
from tcompany
inner join tsearch on tCompany.GUID = tSearch.CompanyGUID
left join tcompanylocation on tcompanylocation.guid= tcompany.LocationGUID
left join tSearchType on tsearchtype.GUID = tSearch.SearchTypeGUID
left join tSearchResult on tSearchResult.GUID = tsearch.SearchResultGUID
left join tPeople on tPeople.GUID = tsearch.PlacedGUID
left join tPosition on tPosition.GUID = tsearch.PositionGUID
left join tDepartment on tdepartment.GUID = tsearch.DepartmentGUID
left join tInstantStatus on tInstantStatus.SearchGUID = tSearch.guid
left join tInstantStatusType on tInstantStatusType.GUID = tInstantStatus.InstantStatusGUID
left join tWorkbench on tWorkbench.SearchGUID=tsearch.GUID
left join tSearchCluendex on tSearchCluendex.CPSGUID=tsearch.GUID
left join tpeopleEducation on tpeople.GUID = tpeopleEducation.PeopleGUID
left join tBusDev on tsearch.GUID = tbusdev.SearchGUID
left join tGenie on tbusdev.GUID = tgenie.BusDevGUID
left join tGenieLink on tGenie.GUID = tgenielink.GenieGUID
left join tGenieLabel on tgenielink.GenieLabelGUID = tGenieLabel.GUID
left join tGenieType on tgenie.GenieTypeGUID=tGenieType.GUID
Weird is that in the system 57 GenieType are defined and only 4 were found. Also with GenieLabel, in the system 16 are defined and only 6 were found.
I am beginner in SQL/TSQL and this query seems quite big .... does it look OK? Or it is hard to tell without more info about DB structure ...
HMMM.... there are different answers suggested, but this above seem to work.
Why should I use:
inner join
inner join
left outer
vs
inner join
left join
left join
vs
join
join
left join
????
Update 2:
Thanks #Daniel for your help. I attached the diagram as you suggested.
What I want to get can be seen in my query from Update 1
Hope some good soul can help.
Your query is performing a CROSS JOIN between tcompany, tsearch and tGenieType, and then tries to join on a corresponding record in the tGenie table. This means your query will return a record for every combination of tcompany, tsearch and tGenieType possible, regardless of any relations between them, and will then try to link the results to tGenie records using your condition, potentially multiplying the results once more.
When you say that you want "all possible entries", what exactly do you want to achieve?
Typically, as well as from your queried columns, you'd want to perform a INNER JOIN or a LEFT JOIN rather than a CROSS JOIN. For example :
SELECT
tSearch.Description,
tCompany.CompanyName,
tSearch.CompanyGUID,
tGenie.GenieNotes,
tGenieType.GenieType
FROM
tCompany
INNER JOIN tSearch ON tCompany.GUID = tSearch.CompanyGUID
LEFT JOIN tGenie ON tSearch.GUID = tGenie.SearchGUID
LEFT JOIN tGenieType ON tGenieType.GUID = tGenie.GenieTypeGUID
This would pull every tSearch from every tCompany, matching them according to their foreign keys, and then try to match with the corresponding tGenie records based on an hypothetical GUID column before doing the same with the tGenieType.
I suggest trying maybe this.
SELECT tsearch.description
,tcompany.CompanyName
,tsearch.CompanyGUID
,tgenie.GenieNotes
,tGenieType.GenieType
FROM tcompany
JOIN tsearch
ON tcompany.SomeID = tsearch.SomeID
JOIN tGenieType
ON tcompany.SomexID = tGenieType.SomexID
LEFT JOIN tGenie
ON tgenie.GenieTypeGUID = tGenieType.GUID
You accidentaly stumbled upon cross join. Also, connecting your tables will have to go over keys, so make sure you identify them correctly. A good visual reference on what's going on with joins is on codinghorror blog.
You are not joining the other tables in FROM (and this syntax is not longer supported in new versions of Sql Server)
Should be like this:
select tsearch.description
,tcompany.CompanyName
,tsearch.CompanyGUID
,tgenie.GenieNotes
,tGenieType.GenieType
from tcompany
inner join tsearch on tcompany.XXX = tsearch.XXX
inner join tGenieType on tcompany.YYY = tsearch.YYY
left outer join tGenie on tgenie.GenieTypeGUID=tGenieType.GUID

Resources