Joining 3 Tables into one result set - sql-server

I am trying to join only select columns from 3 different tables and haven't been successful.
Table 1, Patient, has the following columns I need:
ExternalID, UserDefinedXML, ServiceSiteUid
Table 2, PDI, has the following columns I need:
Patient ID, FirstName, LastName, State
Table 3, ListServiceSite has the following columns I need:
ServiceSiteUid, Name
I need to join Patient and PDI based on the common ID columns ExternalID and PatientID, and then join Patient and ListServiceSite by ServiceSiteUid.
Here's what I have that has been unsuccessful:
SELECT
*
FROM
(SELECT
ExternalID, UserDefinedXml, ServiceSiteUid
FROM
Patient) A
INNER JOIN
(SELECT
[Patient ID], FirstName, LastName, State
FROM
PatDemogImport) B ON A.ExternalID = B.[Patient ID]
WHERE
UserDefinedXml IS NOT NULL;
I am very new to SQL so please have patience! Thank you in advance.

This should do it
SELECT *
FROM Patient as p
JOIN PatDemogImport as pdi
ON p.ExternalID = pdi.[Patient ID]
JOIN ListServiceSite as lss
ON lss.ServiceSiteUid = p.ServiceSiteUid
WHERE p.UserDefinedXml IS NOT NULL;

SELECT * FROM PATIENT
JOIN
PDI on PATIENT.ExternalID = PDI.ExternalID AND PATIENT.PatientID = PDI.PatientID
JOIN
ListServiceSite on ListServiceSite.ServiceSiteUid = PATIENT.ServiceSiteUid
where
UserDefinedXml IS NOT NULL;
That should give you what you're looking for. There's no need for subselects in this instance.
Essentially what you are doing is joining the tables based on the relationship between columns. So in the above we join PDI and PATIENT based on their 2 shared columns and ListServiceSite and PATIENT on ServiceSiteUid.
Please note that when you do a SELECT *, you will get duplicate columns in the result (since you're basically getting all the columns across all those tables) so I'd recommend specifying what you select. i.e. SELECT PATIENT.ExternalID, ....
Finally, I'd recommend reading up on the different kind of joins. The above is just a regular join but there are several others like OUTER JOIN INNER JOIN RIGHT JOIN LEFT JOIN and they all have differences.

SELECT Patient.*
FROM Patient INNER JOIN PatDemogImport as pdi ON
Patient.ExternalID=pdi.Patientid
Inner join ListServiceSite on
Patient.ServiceSiteUid=ListServiceSite.ServiceSiteUid
WHERE Patient.UserDefinedXml IS NOT NULL

Isn't it just as simple as this? You want an inner join and you just need to specify the columns you need. This should give you exactly the answer you're looking for. These other answers have the same idea, but they assume that the tables contain only the columns listed and no other columns. PatientID should be the same as ExternalID so no need to specify that column and C.ServiceSiteUid should be the same as in Patient.
SELECT A.ExternalID, A.UserDefinedXML, A.ServiceSiteUid,
B.FirstName, B.LastName, B.State,
C.Name
FROM Patient A
INNER JOIN PatDemogImport B ON B.PatientID = A.ExternalID
INNER JOIN ListServiceSite C ON C.ServiceSiteUid = A.ServiceSiteUid
WHERE A.UserDefinedXML IS NOT NULL

Related

how to use aggregate query result as column in another query having joins using stored procedures in SQL Server

i have a inner join query in stored procedure which is working fine. i need to inject a aggregate query in it so that it show an aggregated result in a new column
https://drive.google.com/file/d/1tAIEACvEnG7sAisSoE2crYRrzCjIcvST/view?usp=sharing
i tried to inject aggregate query as a column TotalQty in my query
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName, dbo.SOD.SalePrice
,TotalQty = (select SUM(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
But it says
Column 'dbo.SO.Id' is invalid in the select list because it is not
contained in either an aggregate function or the GROUP BY clause.
or any other good Technique suggested will be appreciated.
so change AS :
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName, dbo.SOD.SalePrice
,(select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B') AS TotalQty
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
As in the internal query, your characteristic is you used the o.SOId field on where and in other hand used count aggregate function so you should:
SELECT dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name AS ProductName,
dbo.SOD.SalePrice
,count(dbo.SOD.Quantity) AS TotalQty
FROM dbo.SOD INNER JOIN
dbo.Product ON dbo.SOD.ProductId = dbo.Product.Id RIGHT JOIN
dbo.SO ON dbo.SOD.SOId = dbo.SO.Id INNER JOIN
dbo.Customer ON dbo.SO.CustomerId = dbo.Customer.Id
WHERE (dbo.SO.Id = '68BD0F69-B957-439F-9AD0-180DF23EF42B')
group by
dbo.SO.Id,dbo.Customer.Name, dbo.Product.Name , dbo.SOD.SalePrice
Which will have the same output.
Generally speaking, you encourage others to help if you provide a MVCE. Using cryptic table names (are they tables? or views perhaps?) is not a healthy practice. In addition, it is not clear what you are trying to achieve with your subquery. You attempted to use count but you label the value as "TotalQty" and you replied to a suggestion using "sum". Very confusing.
So since we don't have your tables, I used the common MS sample database AdventureWorks. Below are two examples of counting the quantity values from the detail table.
select Ord.SalesOrderID, Det.SalesOrderDetailID,
Cust.AccountNumber as CustName, -- too lazy to get actual name
Prd.Name as ProductName,
Det.UnitPrice
,Counted.TotalQty
-- TotalQty = (select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
from Sales.SalesOrderHeader as Ord
inner join Sales.SalesOrderDetail as Det on Ord.SalesOrderID = Det.SalesOrderID
inner join Production.Product as Prd on Det.ProductID = Prd.ProductID
inner join Sales.Customer as Cust on Ord.CustomerID = Cust.CustomerID
cross apply (select count(DetCnt.OrderQty) as TotalQty from Sales.SalesOrderDetail as DetCnt where DetCnt.SalesOrderID = Det.SalesOrderID) as Counted
where Ord.SalesOrderID = 43659
select Ord.SalesOrderID, Det.SalesOrderDetailID,
Cust.AccountNumber as CustName, -- too lazy to get actual name
Prd.Name as ProductName,
Det.UnitPrice
, TotalQty = (select count(DetCnt.OrderQty) from Sales.SalesOrderDetail as DetCnt where DetCnt.SalesOrderID = Det.SalesOrderID)
-- TotalQty = (select count(dbo.SOD.Quantity) from [sod] o where o.SOId='68BD0F69-B957-439F-9AD0-180DF23EF42B' )
from Sales.SalesOrderHeader as Ord
inner join Sales.SalesOrderDetail as Det on Ord.SalesOrderID = Det.SalesOrderID
inner join Production.Product as Prd on Det.ProductID = Prd.ProductID
inner join Sales.Customer as Cust on Ord.CustomerID = Cust.CustomerID
where Ord.SalesOrderID = 43659
I think that interpretation is correct but I don't know your schema. I added the PK of the detail table to help "see" the relationship between Order and Detail.
Examine the code closely. Notice how the query only refers to the specific PK value once (this would be your procedure's parameter). You use correlations and joins to limit the results as needed. And notice how much easier it is to understand the query since it uses names that are actual words - SalesOrder vs. SO. I don't think it makes much sense to right join your Detail table to the Order table - seems like a mistake. Your aggregation attempt is odd so I can't say if the value computed by these queries is correct.
I'll also note that you should not be passing the PK value of your table using a nvarchar parameter. Use the correct datatype to avoid the possibility that someone attempts to pass an actual string (e.g., N'Pick me') instead of a GUID value.

Inner join Giving columns Multiple values

I have Three Tables In Database
Table : Group
Id, Name
Table : doctor
Id ,DId, DoctorName,
Table : Ratio
Id , DId, UpLimit , downLimit.
When i inner join them , I am Getting duplicate Values to Uplimit and downlimit,,
Actually Group is related to doctors, One group id can have multple doctors,, so when i save some data with Group and doctor, it is saving to all the records with same data, uplimit downlimit varies with different doctors , but when i inner join dem its showing same to all doctors,, how to skip uplimit and downlimit how to write the Query..
Select A.Group , B.doctor , C.Uplimit, D.downlimit from Group A
inner join Doctor B
on A.id = B.id
inner join C ratio
on A.id = c.id
issue is When i separately check it with doctor id in doctor table it is showing only one record, when i inner join them its showing same data to all doctors to particular
how to join them??
Please use the DISTINCT clause after SELECT. This will filter the duplicates.
Select DISTINCT A.[Group] , B.doctor , C.Uplimit, D.downlimit
FROM Group A
inner join Doctor B
on A.id = B.id
inner join Ratio C
on B.id = C.id
It is good to avoid using the keywords as table/column names.
You Table Structure must be like
Table : Group
Id, Name
Table : doctor
Id ,DId(foreign key for group table), DoctorName
Table : Ratio
Id(Foreign Key for Doctor Table), UpLimit , downLimit.
Ratio Table is either missing a foreign key or a primary key, assuming Id of Ratio table is foreign key
Select A.Group , B.doctor , C.Uplimit, D.downlimit from Group A
inner join Doctor B
on A.id = B.Did
inner join ratio C
on B.id = c.id
This should give what you needed

Sql Query for the following output

I have two tables:
Table_1: (Name, Street, City)
Table_2: (Name, Teacher_Name)
The column Name in Table_1 contains Student's Name as well as Teacher's name while in Table_2 column Name contains only Student's Name and Teacher_Name contains Teacher's Name corresponding to the Student.
So my question is that what will be the SQl query for Finding all students who live in the same Street and City as their Teachers.
please help and thanks in advance.
You need to join Table_1 twice. Like so:
SELECT students.Name, teachers.Name
FROM Table_2 AS teacher_student
JOIN Table_1 AS students ON students.Name = teacher_student.Name
JOIN Table_1 AS teachers ON teachers.Name = teacher_student.Teacher_Name
WHERE students.Street = teachers.Street
AND students.City = teachers.City
Try this query:
SELECT DISTINCT t1.Name
FROM Table_1 t1 INNER JOIN Table_2 t2
ON t1.Name = t2.Name
INNER JOIN Table_1 t3
ON t3.Name = t2.Teacher_Name
WHERE t1.Street = t3.Street AND t1.City = t3.City
You need to join twice to achieve what you want. The first join is necessary to connect the address table with the bridge table of students to teachers. Then you need to join again to get the addresses for those teachers.

How do I name the results of a joined table query

I have two tables and did an inner join on them based on id. Now I need to name this joined table. How do I do that? The reason I want to name this table is because I have to join this result table with some other tables.
You created what is commonly referred t as a relvar, not another table. You can join to it by placing it's SELECT definition in a sub query like this:
SELECT
FROM (
-- original join SQL
) t
INNER JOIN table2 on ...
You can create an alias for the result of a join using a subquery. For example:
select *
from (
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
) as JoinAlias
join tbl3
on JoinAlias.id = tbl3.id
You can often make do without such an alias. For example, consider a third join:
select *
from tbl1
join tbl2
on tbl1.id = tbl2.id
join tbl3
on tbl3.col1 = tbl1.col1
and tbl3.col2 = tbl2.col2
As you can see, the third join's condition can refer to columns from all earlier tables.
select * from (
select * from TableA a join TableB b on a.id = b.a_id
) as p;
As per the comments, it seems that a view might be what you are looking for:
create view MyView
as
select * from TableA a join TableB b on a.id = b.a_id;
It won't be listed in the tables (rather in the views), but will behave just like a table in your sql editor.

SQL UNION INNER JOIN

Im trying to select from 2 tables that have the same columns, but both tables have an inner join -
select e.ID,
c.FullName,
car.VIN,
car.Registration,
e.Telephone,
e.Mobile,
e.Email,
e.EstimateTotal,
e.LastUpdated,
e.LastUpdateBy from (select id from Estimates UNION ALL select id from PrivateEstimates) e
inner join Customers c on c.ID = e.CustomerID
inner join Cars car on car.ID = e.CarID
where e.Status = 0
The trouble is, it can't find e.CustomerID, e.CarID or e.Status on the inner join? Any ideas?
Your subquery
select id from Estimates
union all
select id from PrivateEstimates
returns only a single id column. Include necessary columns in the subquery if you want to use those columns in JOIN statements

Resources