how to select a record from multiple tables [closed] - tsql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'd be glad if someone could show me how I can select a record from 12 tables.
The main issue is that I have a table for each subject for storing marks obtained by students.
Each subject table has the following columns: StudentId, RegId, AcademicYear, Term, Form, ClassScore, ExamScore, Total, Grade.
The studentDetails.Students table which contains students demographic record has StudentId column as its primary key.

There are a couple of different ways that you can return the data.
You can use a JOIN between the students table and all of the subjects tables:
select * -- replace this with the columns you want to return
from Students s
left join subject1 s1
on s.studentid = s1.studentid
left join subject2 s2
on s.studentid = s2.studentid
left join subject3 s3
on s.studentid = s3.studentid
left join subject4 s4
on s.studentid = s4.studentid;
See SQL Fiddle with demo
Or you can use something like the following which joins the students table with a subquery that uses a UNION ALL between each subject table:
select s.StudentId, S.StudentName, S.Photo,
sb.StudentId, sb.RegId, sb.AcademicYear,
sb.Term, sb.Form, sb.ClassScore, sb.ExamScore, sb.Total, sb.Grade
from students s
inner join
(
select s1.StudentId, s1.RegId, s1.AcademicYear,
s1.Term, s1.Form, s1.ClassScore, s1.ExamScore, s1.Total, s1.Grade,
'Subject1' as src
from subject1 s1
union all
select s2.StudentId, s2.RegId, s2.AcademicYear,
s2.Term, s2.Form, s2.ClassScore, s2.ExamScore, s2.Total, s2.Grade,
'Subject2' as src
from subject2 s2
union all
select s3.StudentId, s3.RegId, s3.AcademicYear,
s3.Term, s3.Form, s3.ClassScore, s3.ExamScore, s3.Total, s3.Grade,
'Subject3' as src
from subject3 s3
) sb
on s.studentid = sb.studentid
See SQL Fiddle with Demo
If you have another table that you want to join, then you will use:
select s.StudentId, S.StudentName, S.Photo,
sb.StudentId, sb.RegId, sb.AcademicYear,
sb.Term, sb.Form, sb.ClassScore, sb.ExamScore, sb.Total, sb.Grade,
r.programofstudy
from students s
inner join
(
select s1.StudentId, s1.RegId, s1.AcademicYear,
s1.Term, s1.Form, s1.ClassScore, s1.ExamScore, s1.Total, s1.Grade,
'Subject1' as src
from subject1 s1
union all
select s2.StudentId, s2.RegId, s2.AcademicYear,
s2.Term, s2.Form, s2.ClassScore, s2.ExamScore, s2.Total, s2.Grade,
'Subject2' as src
from subject2 s2
union all
select s3.StudentId, s3.RegId, s3.AcademicYear,
s3.Term, s3.Form, s3.ClassScore, s3.ExamScore, s3.Total, s3.Grade,
'Subject3' as src
from subject3 s3
) sb
on s.studentid = sb.studentid
left join Registration r
on s.studentid = r.studentid
and sb.regid = r.regid

An example using a union query:
SELECT au_lname FROM authors
UNION ALL
SELECT lname FROM Employee
ORDER BY au_lname

Related

How to find in a many to many relation all the identical values in a column and join the table with other three tables?

I have a many to many relation with three columns, (owner_id,property_id,ownership_perc) and for this table applies (many owners have many properties).
So I would like to find all the owner_id who has many properties (property_id) and connect them with other three tables (Table 1,3,4) in order to get further information for the requested result.
All the tables that I'm using are
Table 1: owner (id_owner,name)
Table 2: owner_property (owner_id,property_id,ownership_perc)
Table 3: property(id_property,building_id)
Table 4: building(id_building,address,region)
So, when I'm trying it like this, the query runs but it returns empty.
SELECT address,region,name
FROM owner_property
JOIN property ON owner_property.property_id = property.id_property
JOIN owner ON owner.id_owner = owner_property.owner_id
JOIN building ON property.building_id=building.id_building
GROUP BY owner_id,address,region,name
HAVING count(owner_id) > 1
ORDER BY owner_id;
Only when I'm trying the code below, it returns the owner_id who has many properties (see image below) but without joining it with the other three tables:
SELECT a.*
FROM owner_property a
JOIN (SELECT owner_id, COUNT(owner_id)
FROM owner_property
GROUP BY owner_id
HAVING COUNT(owner_id)>1) b
ON a.owner_id = b.owner_id
ORDER BY a.owner_id,property_id ASC;
So, is there any suggestion on what I'm doing wrong when I'm joining the tables? Thank you!
This query:
SELECT owner_id
FROM owner_property
GROUP BY owner_id
HAVING COUNT(property_id) > 1
returns all the owner_ids with more than 1 property_ids.
If there is a case of duplicates in the combination of owner_id and property_id then instead of COUNT(property_id) use COUNT(DISTINCT property_id) in the HAVING clause.
So join it to the other tables:
SELECT b.address, b.region, o.name
FROM (
SELECT owner_id
FROM owner_property
GROUP BY owner_id
HAVING COUNT(property_id) > 1
) t
INNER JOIN owner_property op ON op.owner_id = t.owner_id
INNER JOIN property p ON op.property_id = p.id_property
INNER JOIN owner o ON o.id_owner = op.owner_id
INNER JOIN building b ON p.building_id = b.id_building
ORDER BY op.owner_id, op.property_id ASC;
Always qualify the column names with the table name/alias.
You can try to use a correlated subquery that counts the ownerships with EXISTS in the WHERE clause.
SELECT b1.address,
b1.region,
o1.name
FROM owner_property op1
INNER JOIN owner o1
ON o1.id_owner = op1.owner_id
INNER JOIN property p1
ON p1.id_property = op1.property_id
INNER JOIN building b1
ON b1.id_building = p1.building_id
WHERE EXISTS (SELECT ''
FROM owner_property op2
WHERE op2.owner_id = op1.owner_id
HAVING count(*) > 1);

COALESCE TSQL with a join tsql

I have a requirement to pick up data that is in more than one place and I have some form of recognition if using the coalesce function. Basically I am looking to coalesce the join itself but looking online its seems as if i can only do this on the fields.
So we have a Products and Suppliers table, we also have these as a temp table so in total 4 tables (products, tempproducts, suppliers, tempsuppliers). In the suppliers and products table is where we store our products and suppliers and their temptables we store any new suppliers/products. We also have a tempsupplierproduct which joins new suppliers to new products. However we can end in a situation where a new supplier has an existing product so the new supplier will be in the tempsuppliers table and its product is in the products table NOT the tempproducts as it is not new, we will also have a new tempsupplierproduct to join the two up.
So i want a query which looks in the tempsupplierproducts table and then gets basic information about the supplier and products. To do this i am using a coalesce.
SELECT DISTINCT SP.*, COALESCE(P.Product, PD.Product) 'Product', COALESCE(S.Supplier, SU.Supplier) 'Supplier'
FROM tempsupplierproduct SP
LEFT JOIN tempProduct P ON SP.ProductCode = P.Code
LEFT JOIN Products PD ON SP.ProductCode = PD.Code
LEFT JOIN tempSupplier S ON SP.SupplierCode = S.Code
LEFT JOIN Suppliers SU ON SP.SupplierCode = SU.Code
Now while this works, something at the back of my head tells me it is not entirely right, ideally i want if data is not in table A then join to table B. I have seen maybe coalescing inside the join itself but I am unsure how to do this
LEFT JOIN Suppliers Su ON SP.SupplierCode = COALESCE(S.Code, SU.Code)
maybe away, but I am confused by this, all it is saying is use code in temptable if not there then use supplier code. So what would this mean if we have a code in the temptable, will this try to join on it, if so then this is incorrect also.
Any help is appreciated
You can union the two suppliers tables together and then join them in one go like this. I'm assuming that there are no duplicates between the two tables in this case but with a bit of extra work that could be resolved as well.
WITH AllSuppliers AS
(
SELECT Code, Supplier FROM Suppliers
UNION ALL
SELECT Code, Supplier FROM tempSupplier
)
SELECT DISTINCT SP.*, COALESCE(P.Product, PD.Product) 'Product', S.Supplier
FROM tempsupplierproduct SP
LEFT JOIN tempProduct P ON SP.ProductCode = P.Code
LEFT JOIN Products PD ON SP.ProductCode = PD.Code
LEFT JOIN AllSuppliers S ON SP.SupplierCode = S.Code
If you need to handle duplicates in the two suppliers tables then an approach like this should work, essentially we rank the duplicates and then pick the highest ranked result. For two tables you could use a full outer join between the two but this approach will scale to any number of tables.
WITH AllSuppliers AS
(
SELECT Code, Supplier, 1 AS TablePriority FROM Suppliers
UNION ALL
SELECT Code, Supplier, 2 AS TablePriority FROM tempSupplier
),
SuppliersRanked AS
(
SELECT Code, Supplier,
ROW_NUMBER() OVER (PARTITION BY Code ORDER BY TablePriority) AS RowPriority
FROM AllSuppliers
)
SELECT DISTINCT SP.*, COALESCE(P.Product, PD.Product) 'Product', S.Supplier
FROM tempsupplierproduct SP
LEFT JOIN tempProduct P ON SP.ProductCode = P.Code
LEFT JOIN Products PD ON SP.ProductCode = PD.Code
LEFT JOIN SuppliersRanked S ON SP.SupplierCode = S.Code
AND RowPriority = 1
You can absolutely join on a coalesced field. Here is a snippet from one of my production views:
LEFT JOIN [Portal].tblHelpdeskresource supplier ON PO.fld_str_SupplierID = supplier.fld_str_SupplierID
-- Job type a
LEFT JOIN [Portal].tblHelpDeskFault HDF ON PO.fld_int_HelpdeskFaultID = HDF.fld_int_ID
-- Job Type b
LEFT JOIN [Portal].tblProjectHeader PH ON PO.fld_int_ProjectHeaderID = PH.fld_int_ID
LEFT JOIN [Portal].tblPPMScheduleLine PSL ON PH.fld_int_PPMScheduleRef = PSL.fld_int_ID
-- Managers (used to be separate for a & b type, now converged)
LEFT JOIN [Portal].uvw_HelpDeskSiteManagers PSM ON COALESCE(PSL.fld_int_StoreID,HDF.fld_int_StoreID) = PSM.PortalSiteId
LEFT JOIN [Portal].tblHelpdeskResource PHDR ON PSM.PortalResourceId = PHDR.fld_int_ID

DB2 SQL update more than 1 columns correlating with subquery [duplicate]

This question already has answers here:
SQL update from one Table to another based on a ID match IN db2
(6 answers)
Closed 3 years ago.
I’m new in DB2 but not new in SQL and new a DB2 SQL update correlating with subquery in DB2 LUW V9.5. My Table is like below:
In rows 3 and 7 I need to update ACTIVE = 0 and VALID_TO = VALID_FROM from Rows 4 and 8 (SCD). I select data using below Statement:
SELECT T2.COL1, T2.COL1_HIST, T2.ACTIVE, T2.VALID_FROM, T2.VALID_TO, T3.VALID_FROM
FROM TMP.TABLE01 T2 INNER JOIN
(
SELECT COL1, MAX(COL1_HIST) MAX_HIST FROM TMP.TABLE01 WHERE
ACTIVE = 1
GROUP BY COL1
HAVING Count(*)>1
)T1 ON T2.COL1 = T1.COL1 AND T2.COL1_HIST < T1.MAX_HIST
INNER JOIN TMP.TABLE01 T3 ON T1.COL1 = T3.COL1 AND T1.MAX_HIST = T3.COL1_HIST
WHERE T2.ACTIVE = 1
To update in SQL world, I can use below statement:
UPDATE T2 SET T2.ACTIVE = 0,T2.VALID_TO=T3.VALID_FROM
FROM TMP.TABLE01 T2 INNER JOIN
(
SELECT COL1, MAX(COL1_HIST) MAX_HIST FROM TMP.TABLE01 WHERE
ACTIVE = 1
GROUP BY COL1
HAVING Count(*)>1
)T1 ON T2.COL1 = T1.COL1 AND T2.COL1_HIST < T1.MAX_HIST
INNER JOIN TMP.TABLE01 T3 ON T1.COL1 = T3.COL1 AND T1.MAX_HIST = T3.COL1_HIST
WHERE T2.ACTIVE = 1
How could this be in DB2 (DB2 LUW V9.5) world?
I know the similar Question in Stack Overflow, but it does not help me :( link
Many thanks in advance
Try this:
merge into table01 a using
(
select rownumber() over(partition by col1 order by col1_hist desc) rn_, t.*
from table01 t
where active=1
) m on m.rn_=1 and a.active=1 and a.col1=m.col1 and a.col1_hist<>m.col1_hist
when matched then update set active=0, valid_to=m.valid_from;
rn_ column of the inner subselect has value 1 for each row with the highest col1_hist in a group of records with the same col1.
We update all other active rows except these ones with correct valid_from value for each group.

Access or general query question about grouping 2 lines of data where [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
Access or general query question about grouping 2 lines of data where for example all the columns are all the same except for amount and last 1 field which is vendor id.. I have an exceptions list where if the vendor ID is in exception list don't use that use the other one then group..
Any suggestions?
e.g.
V124 is in exceptions list
Answer should be
ID1 $13 V123...
Do I use union?? or what? thanks.
I tried subquery but erros out.
vid: (SELECT Table1.Vendor
FROM Table1 LEFT JOIN [tl_List of Exceptions] ON Table1.Vendor = [tl_List of Exceptions].[Vendor ID]
WHERE ((([tl_List of Exceptions].[Vendor ID]) Is Null))
group by table1.[Vendor];)
This is my test query..
SELECT Table1.[Outstanding Amount], Table1.[FMMI Obl Doc Nbr],
(SELECT Table1.Vendor, [tl_List of Exceptions].[Vendor ID]
FROM Table1 LEFT JOIN [tl_List of Exceptions] ON Table1.Vendor = [tl_List of Exceptions].[Vendor ID]
WHERE ((([tl_List of Exceptions].[Vendor ID]) Is Null));) AS vendor
FROM Table1;
Trying to make this work.. any suggestions on adding the subquery? Thanks.
SELECT DISTINCT A.[Outstanding Amount], A.[FMMI Obl Doc Nbr], A.vendor
FROM Table1 AS A, [tl_List of Exceptions] AS b
WHERE (((A.vendor)<>[b].[vendor ID]));
Lee:
select v.[Doc Nbr], u.tot, first(v.[Vendor]) as vendor
from
(
[2_concatrelated] v inner join
(
select t.[Doc Nbr], sum(t.[Outstanding Amount]) as tot
from [2_concatrelated] t
group by t.[Doc Nbr]
) u on v.[Doc Nbr] = u.[Doc Nbr]
) left join [tl_List of Exceptions] e on v.[Vendor] = e.[Vendor id]
where
e.[Vendor id] is null
group by
v.[Doc Nbr], u.tot
Based on the limited information you have provided, I would suggest calculating the totals using a subquery (in which all vendors are included), and then excluding the appropriate vendors from the parent query, e.g.:
select v.col1, u.tot, first(v.col3) as vendor
from
(
table1 v inner join
(
select t.col1, sum(t.col2) as tot
from table1 t
group by t.col1
) u on v.col1 = u.col1
) left join [tl_List of Exceptions] e on v.col3 = e.[Vendor ID]
where
e.[Vendor ID] is null
group by
v.col1, u.tot
Assumed that your tables are called Table1 and tl_List of Exceptions and that your fields are Table1.col1, Table1.col2, Table1.col3, and tl_List of Exceptions.Vendor ID

How to design a SQL recursive query?

How would I redesign the below query so that it will recursively loop through entire tree to return all descendants from root to leaves? (I'm using SSMS 2008). We have a President at the root. under him are the VPs, then upper management, etc., on down the line. I need to return the names and titles of each. But this query shouldn't be hard-coded; I need to be able to run this for any selected employee, not just the president. This query below is the hard-coded approach.
select P.staff_name [Level1],
P.job_title [Level1 Title],
Q.license_number [License 1],
E.staff_name [Level2],
E.job_title [Level2 Title],
G.staff_name [Level3],
G.job_title [Level3 Title]
from staff_view A
left join staff_site_link_expanded_view P on P.people_id = A.people_id
left join staff_site_link_expanded_view E on E.people_id = C.people_id
left join staff_site_link_expanded_view G on G.people_id = F.people_id
left join facility_view Q on Q.group_profile_id = P.group_profile_id
Thank you, this was most closely matching what I needed. Here is my CTE query below:
with Employee_Hierarchy (staff_name, job_title, id_number, billing_staff_credentials_code, site_name, group_profile_id, license_number, region_description, people_id)
as
(
select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
where A.last_name = 'kromer'
)
select C.staff_name, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
from staff_view A
left join staff_site_link_expanded_view C on C.people_id = A.people_id
left join facility_view Q on Q.group_profile_id = C.group_profile_id
left join regions R on R.regions_id = Q.regions_id
WHERE C.STAFF_NAME IS NOT NULL
GROUP BY C.STAFF_NAME, C.job_title, C.id_number, C.billing_staff_credentials_code, C.site_name, C.group_profile_id, Q.license_number, R.region_description, A.people_id
ORDER BY C.STAFF_NAME
But I am wondering what is the purpose of the "Employee_Hierarchy"? When I replaced "staff_view" in the outer query with "Employee_Hierarchy", it only returned one record = "Kromer". So when/where can we use "Employee_Hierarchy"?
See:
SQL Server - Simple example of a recursive CTE
MSDN: Recursive Queries using Common Table Expression
SQL Server recursive CTE (this seems pretty much like exactly what you are working on!)
Update:
A proper recursive CTE consist of basically three things:
an anchor SELECT to begin with; that can select e.g. the root level employees (where the Reports_To is NULL), or it can select any arbitrary employee that you define, e.g. by a parameter
a UNION ALL
a recursive SELECT statement that selects from the same, typically self-referencing table and joins with the recursive CTE being currently built up
This gives you the ability to recursively build up a result set that you can then select from.
If you look at the Northwind sample database, it has a table called Employees which is self-referencing: Employees.ReportsTo --> Employees.EmployeeID defines who reports to whom.
Your CTE would look something like this:
;WITH RecursiveCTE AS
(
-- anchor query; get the CEO
SELECT EmployeeID, FirstName, LastName, Title, 1 AS 'Level', ReportsTo
FROM dbo.Employees
WHERE ReportsTo IS NULL
UNION ALL
-- recursive part; select next Employees that have ReportsTo -> cte.EmployeeID
SELECT
e.EmployeeID, e.FirstName, e.LastName, e.Title,
cte.Level + 1 AS 'Level', e.ReportsTo
FROM
dbo.Employees e
INNER JOIN
RecursiveCTE cte ON e.ReportsTo = cte.EmployeeID
)
SELECT *
FROM RecursiveCTE
ORDER BY Level, LastName
I don't know if you can translate your sample to a proper recursive CTE - but that's basically the gist of it: anchor query, UNION ALL, recursive query