3 tables:
Mark table:
student_id sa_id marks
1 1 75
1 2 80
1 3 100
2 4 85
2 5 90
2 6 60
course table:
course_code sat_id name_code
AAA 100 1 midterm1
AAA 100 2 midterm2
AAA 100 3 final
BBB 200 4 midterm1
BBB 200 5 midterm2
BBB 200 6 final
transform table:
sa_id sat_id
1 1
2 2
3 3
4 4
5 5
6 6
select course.course_code, mark.marks
from mark
left outer join transform on transform.sa_id = mark.sa_id
left outer join course on course.sat_id = transfrom.sat_id
where course.name_code = 'midterm1'
At the above query only midterm1 result, also we can extract mid2 and final
select mark.student_id,course.course_code, mark.marks, course.name_code
from mark
left outer join transform on transform.sa_id = mark.sa_id
left outer join course on course.sat_id = transfrom.sat_id
order by mark.student_id, course.course_code
Result will give:
student_id course_code marks name_code
1 AAA 100 75 midterm1
1 AAA 100 80 midterm2
1 AAA 100 100 final
2 BBB 200 85 midterm1
2 BBB 200 90 midterm2
2 BBB 200 60 final
So how to build query that should be
student_id course_code midterm1 midterm2 final
1 AAA 100 75 80 100
2 BBB 200 85 90 60
You can use case when , group by (and a fake aggregation function)
select
student_id
, course_code
, max(case when name_code ='midterm1' then mark else null) midterm1
, max(case when name_code ='midterm2' then mark else null) midterm2
, max(case when name_code ='final' then mark else null) final
from mark
left outer join transform on transform.sa_id = mark.sa_id
left outer join course on course.sat_id = transfrom.sat_id
group by student_id, course_code
order by mark.student_id, course.course_code
But if you don't like aggregation functio you can use a 3 seleft join on mark
select
mm1.student_id
, mm1.course_code
, mm1.mark midterm1
, mm2.mark midterm2
, mm3.mark finale
from mark as mm1
left join mark as mm2 on mm1.student_id = mm2.student_id and mm1.course_code = mm2.course_code
left join mark as mm3 on mm1.student_id = mm3.student_id and mm1.course_code = mm3.course_code
left outer join transform on transform.sa_id = mm1.sa_id
left outer join course on course.sat_id = transfrom.sat_id
where mm1.name_code = 'midterm1'
and mm2.name_code = 'midterm2'
and mm3.name_code = 'final'
Related
List the project numbers (PR_NO) for projects that have only received parts that are stored in (P_CITY) the same city as the project (show output of the query).
Table: EMP
Primary Key: E_NO
E_NO E_NAME E_RATE E_DEPT
1 A $400.00
2 B $200.00 1
3 C $150.00 2
4 D $150.00 3
5 E $120.00 1
6 F $100.00 1
7 G $100.00 2
8 H $50.00 2
9 I $50.00 3
10 J $50.00 3
11 K $150.00 3
Table: PART
Primary Key: P_NO
P_NO P_NAME P_CITY
1 P1 NY
2 P2 NY
3 P3 LA
4 P4 SF
5 P5 LA
6 P6 NY
Table: PROJECT
Primary Key: PR_NO
PR_NO PR_MGR PR_DEPT PR_LOC
1 2 1 NY
2 3 2 LA
3 2 1 NY
Table: SUPPLIER
Primary Key: S_NO
S_NO S_NAME S_LOC
1 S1 NY
2 S2 NY
3 S3 LA
Table: SUPPLY
Primary Key: P_NO + PR_NO + S_NO
Foreign Key: P_NO references PART
Foreign Key: PR_NO references PROJECT
Foreign Key: S_NO references SUPPLIER
P_NO PR_NO S_NO QTY
1 1 1 111
1 1 2 112
1 1 3 113
1 2 1 121
1 2 2 122
1 2 3 123
1 3 1 131
1 3 2 132
1 3 3 133
2 1 1 211
3 1 1 311
4 1 1 411
5 1 1 511
6 1 1 611
Table: WORK
Primary Key: E_NO + PR_NO
Foreign Key: E_NO references EMP
Foreign Key: PR_NO references PROJECT
E_NO PR_NO HRS
2 1 10
3 2 20
5 1 20
5 2 20
5 3 20
6 1 10
6 2 10
select distinct P.PR_NO
from PROJECT P, PART PA
where PA.P_CITY = P.PR_LOC;
The right answer question should be :
PR_NO
3
This is the error:
PR_NO
1
3
2
In order to achieve this task, you also need to use Supply table as follows:
select s.pr_no
from supply s
inner join part p
on p.p_no = s.p_no
group by s.pr_no
having max(p.p_city) = min(p.p_city)
and min(p.p_city) = (select pr_loc
from project
where pr_no = s.pr_no
)
I tested this query with your example data and it returns project #3 as expected:
SELECT DISTINCT S.PR_NO
FROM
SUPPLY S
INNER JOIN PROJECT PR
ON S.PR_NO = PR.PR_NO
INNER JOIN PART P
ON S.P_NO = P.P_NO
WHERE
PR.PR_LOC = P.P_CITY AND
NOT S.PR_NO IN
(
SELECT S2.PR_NO
FROM
SUPPLY S2
INNER JOIN PROJECT PR2
ON S2.PR_NO = PR2.PR_NO
INNER JOIN PART P2
ON S2.P_NO = P2.P_NO
WHERE PR2.PR_LOC <> P2.P_CITY
)
The SUPPLY table creates the link between PART and PROJECT. The main query looks for parts that are stored in the same city as the project. The sub-select in the where clause looks almost the same, except that it looks for parts stored in a different city. Projects with such cities are excluded with NOT S.PR_NO IN (...).
The main issue in your query is that you should correctly join the 2 tables PROJECT and PART before filtering; so in this case you should use the table SUPPLY.
SELECT DISTINCT S.PR_NO
FROM SUPPLY S
INNER JOIN PROJECT PR
ON S.PR_NO = PR.PR_NO
INNER JOIN PART P
ON S.P_NO = P.P_NO
WHERE PR.PR_LOC = P.P_CITY
AND S.PR_NO NOT IN ( SELECT DISTINCT S.PR_NO
FROM SUPPLY S
INNER JOIN PROJECT PR
ON S.PR_NO = PR.PR_NO
INNER JOIN PART P
ON S.P_NO = P.P_NO
WHERE PR.PR_LOC <> P.P_CITY );
Hope this helps!
I have 2 tables:
Table1 - Criteria
Office_ID Bus_Stream Bus_Criteria Crit_Value
1 ABC 0 20
1 ABC 1 21
1 ABC 2 7
2 ABC 0 15
2 ABC 1 12
2 ABC 2 21
3 XYZ 1 17
3 XYZ 2 3
Table2 - Limit
Bus_Stream GroupID TypeID SubgroupID Bus_Limit
ABC 20 21 7 50
ABC 15 12 21 100
XYZ 99 17 3 120
I need to create a join that allows me to pull back:
Result
Bus_Stream Office_ID GroupID TypeID SubgroupID Bus_Limit
ABC 1 20 21 7 50
ABC 2 15 12 21 100
XYZ 3 (null) 17 3 120
Essentially, I need to join Table1.Crit_Value based on the following:
Table1.Bus_Criteria Table2
0 GroupID
1 TypeID
2 SubGroupID
with the added complication that if one or two of the 0/1/2 values from Bus_Criteria is missing, the joins will still occur on the remaining criteria.
I have tried a number of combinations of AND/OR on the join to no avail.
Any ideas folks?
This may be what you're after.. use a case statement on the join.
The problem here is your data in t2 isn't normalized, you could also unpivot the 3 data columns in t2 so the join is more natural.
SELECT T2.Bus_Stream, T1.Office_ID, T2.GroupID, T2.TypeID, T2.SubGroupId, T2.bus_Limit
FROM T1
INNER JOIN T2
on T1.Bus_Stream = T2.Bus_Stream
and T1.Crit_value = case when T1.Bus_Critiera = 0 then T2.GroupID
when T1.Bus_Critiera = 1 then T2.TypeID
when T1.Bus_Critiera = 2 then T2.SubGroupID
end
Did you try something like this?
SELECT
t1.*, t2.*
FROM Table1 t1
INNER JOIN Table2 t2 ON
t1.Bus_Stream = t2.Bus_Stream AND
CASE
WHEN t1.Bus_Criteria = 0
THEN t2.GroupID = t1.Crit_Value
WHEN t1.Bus_Criteria = 1
THEN t2.TypeID = t1.Crit_Value
ELSE
t2.SubGroupID = t1.Crit_Value
END
I have following data
Components
componentid title
1 houseRent
2 medical
3 Travelling Allowance
empPayrollMaster
MasterID EmployeeID SalaryMonthID
1 101 1
2 102 1
3 103 1
empPayrollDetail
DetailID MasterID ComponentID amount
1 1 1 100
2 1 2 500
3 2 1 300
4 2 3 250
5 3 1 150
6 3 2 350
7 3 3 450
Required Output
EmployeeID MasterID ComponentID amount
101 1 1 100
101 1 2 500
101 1 3 0
102 2 1 300
102 1 2 0
102 2 3 250
103 3 1 150
103 3 2 350
103 3 3 450
To get the required output if i do left outer join between components and empPayrollDetail I get null in EmployeeID and MasterID and amount Columns. How to modify left join to get the required output
You need to do a CROSS JOIN on Components and empPayrollMaster to generate first all combination of employees and components. Then, do a LEFT JOIN on empPayrollDetail to achieve the result, using ISNULL(amount, 0) for NULL amounts.
SQL Fiddle
SELECT
epm.EmployeeID,
epm.MasterID,
c.ComponentID,
amount = ISNULL(epd.amount, 0)
FROM empPayrollMaster epm
CROSS JOIN Components c
LEFT JOIN empPayrollDetail epd
ON epd.MasterID = epm.MasterID
AND epd.ComponentID = c.ComponentID
Try this
select empPayrollMaster.EmployeeID,empPayrollMaster.MasterID,
Components.componentid,isnull(empPayrollDetail.amount,0)
from empPayrollMaster
left join Components
on empPayrollMaster.EmployeeID is not null
left join empPayrollDetail
on empPayrollDetail.MasterID = empPayrollMaster.MasterID
and empPayrollDetail.ComponentID = Components.componentid
Try this way
select c.EmployeeID,d.MasterID,c.ComponentID,isnull(d.amount,0) as amount from (
select * from Components a
Cross join empPayrollMaster b) c
left outer join empPayrollDetail d on d.componentid =c.componentid
As you want the component amount for each employee in the master table you should use a insull(payrole_detail.amount,0) or, as #Turophile pointed out, the SQL standard function coalesce(payrole_detail.amount,0) for the amounts column.
SELECT Customers.CustomerName, Orders.OrderID
FROM Customers
INNER JOIN Orders
ON Customers.CustomerID=Orders.CustomerID
ORDER BY Customers.CustomerName;
Table : Class
class_id ClassName
----------------------
1 AAA
2 BBB
3 CCC
Table : Groups
id class_id GroupName
---------------------------
1 1 A1
2 1 A2
3 2 B1
4 3 C1
5 2 B2
6 1 A3
Expected Output :
class_id ClassName count(*)
-------------------------------
1 AAA 3
2 BBB 2
3 CCC 1
Use Inner Join to get result :
SELECT Class.class_id, Class.ClassName, COUNT(*) AS count
FROM Class INNER JOIN
Groups ON Class.class_id = Groups.class_id
GROUP BY Class.class_id, Class.ClassName
I have three tables.
Table 1:
Student
----------
studentID
StudentName
Table 2:
Studentmarks
----------------
studentID
subjectId
marks
Table 3:
Subject
---------
subjectID
subjectName
I need a query to get top 3 students in each subject.
I want output like:
----------------------------------------------------------------
StudentID Name subjectId subjectName marks
-----------------------------------------------------------------
1 AAA 1 phy 85
2 BBB 1 phy 75
3 CCC 1 phy 65
3 CCC 2 bio 85
4 DDD 2 bio 75
1 AAA 2 bio 65
6 FFF 3 che 85
1 AAA 3 che 75
5 EEE 3 che 65
3 CCC 4 mat 85
2 BBB 4 mat 75
4 DDD 4 mat 65
WITH CTE
AS
(
SELECT
s.StudentID,
s.StudentName,
sm.subjectId,
j.SubjectName,
sm.marks,
ROW_NUMBER() OVER(PARTITION BY sm.subjectId
ORDER BY sm.marks DESC) AS RN
FROM student AS s
INNER JOIN Studentmarks AS sm ON s.studentID = sm.studentID
INNER JOIN Subject AS j ON sm.subjectId = j.SubjectId
)
SELECT
StudentID,
StudentName,
subjectId,
SubjecTName,
marks
FROM CTE
WHERE RN <= 1;