Query for Joining three tables with row value as column header - sql

I have three tables as shown below.
TABLE1 : tb_subject
subject_id subject_name
1 English
2 Maths
3 Science
Table2 : tb_student
subject_id student_id
1 AA
1 BB
2 CC
3 DD
3 EE
Table3 : tb_student_score
student_id score conducted_month_number
AA 20 2
BB 30 3
CC 50 4
AA 80 4
DD 50 6
BB 10 2
EE 40 3
Result should be
conducted_month_number SUM(subject_id1) SUM(subject_id2) SUM(subject_id3)
1 0 0 0
2 30 0 0
3 30 0 40
4 80 50 0
5 0 0 0
6 0 0 60
7 0 0 0
8 0 0 0
9 0 0 0
10 0 0 0
11 0 0 0
12 0 0 0
How to write a select query for this? Can add all month number that is not stored in table as like in the resulted output?

You should be able to use case when to sum for each subject individually:
SELECT conducted_month_number,
SUM(CASE b.subject_id WHEN 1 THEN a.score ELSE 0 END) AS English,
SUM(CASE b.subject_id WHEN 2 THEN a.score ELSE 0 END) AS Maths,
SUM(CASE b.subject_id WHEN 3 THEN a.score ELSE 0 END) AS Science
FROM tb_student_score AS a
JOIN tb_student AS b ON b.student_id = a.student_id
GROUP BY conducted_month_number
ORDER BY conducted_month_number;
However, this alone will not ensure you have results for values of conducted_month_number that don't exist - if this is an issue, you could simply create a dummy student with a score of 0 for each month.
Edit: I noticed some comments posted around the same time I submitted my answer - if you want the number of summation columns to be variable based on the values of rows in the tb_subject table, you will not find the relational model of SQL to be well suited for that task. However, you can easily go back and update your query to include any new subjects you may add later on.

Have added dummy values of 1 to 12 months using union statement and later on did group by on them to calculate total scores.
Try this:-
Select conducted_month_number ,
sum(case when subject_id=1 then score else 0 end) as sum_subject_id1,
sum(case when subject_id=2 then score else 0 end) as sum_subject_id2,
sum(case when subject_id=3 then score else 0 end) as sum_subject_id3
from
(
Select a.conducted_month_number ,subject_id,score
from
tb_student_score a
inner join
tb_student b
on a.student_id=b.student_id
union
select 1,' ',0 from tb_student_score
union
select 2,' ',0 from tb_student_score
union
select 3,' ',0 from tb_student_score
union
select 4,' ',0 from tb_student_score
union
select 5,' ',0 from tb_student_score
union
select 6,' ',0 from tb_student_score
union
select 7,' ',0 from tb_student_score
union
select 8,' ',0 from tb_student_score
union
select 9,' ',0 from tb_student_score
union
select 10,' ',0 from tb_student_score
union
select 11,' ',0 from tb_student_score
union
select 12,' ',0 from tb_student_score
)a
group by conducted_month_number
My Output
conducted_month_number sum_subject_id1 sum_subject_id2 sum_subject_id3
1 0 0 0
2 30 0 0
3 30 0 40
4 80 50 0
5 0 0 0
6 0 0 50
7 0 0 0
8 0 0 0
9 0 0 0
10 0 0 0
11 0 0 0
12 0 0 0

Related

Creating a view from two tables, with case and sum on one table

I'm having some troubles trying to create a view from two tables, which includes a sum + case for the first table. I've tried multiple different joins/unions, and I can get just the XTS table to come over, or just the case count scenarios to work, but I cannot get both.
here are the tables. For Table 1, UWI is non-unique. For Table 2, UWI is Unique. new_view is what I'm hoping to achieve for my view.
TABLE 1
UWI ET
1 A
1 B
1 B
2 B
2 C
2 C
TABLE 2
UWI XTS
1 10
2 20
3 10
4 30
new_view
UWI XTS B_COUNT C_COUNT
1 10 4 3
2 20 3 4
3 10 4 5
4 30 3 2
Here's what I'm currently working with.
CREATE VIEW new_view AS
SELECT t1.UWI,
sum(case when t1.ET='B' then 1 else 0 end) as B_COUNT,
sum(case when t1.ET='C' then 1 else 0 end) as C_COUNT,
sum(case when t1.ET='D' then 1 else 0 end) as D_COUNT,
sum(case when t1.ET='E' then 1 else 0 end) as E_COUNT,
sum(case when t1.ET='F' then 1 else 0 end) as F_COUNT
FROM TABLE_1 t1
INNER JOIN (SELECT t2.UWI, t2.XTS AS TSC
from TABLE_2 t2)
on t1.UWI = t2.UWI
group by t1.UWI;
Your sample select does not match your sample data, so this is a guess but I think you just need to move the aggregation into an apply()
select t2.UWI, t2.XTS, s.*
from Table_2 t2
outer apply (
select
sum(case when t1.ET='B' then 1 else 0 end) as B_COUNT,
sum(case when t1.ET='C' then 1 else 0 end) as C_COUNT,
sum(case when t1.ET='D' then 1 else 0 end) as D_COUNT,
sum(case when t1.ET='E' then 1 else 0 end) as E_COUNT,
sum(case when t1.ET='F' then 1 else 0 end) as F_COUNT
from table_1 t1
where t1.UWI = t2.UWI
group by t1.UWI
)s

Get data based on condition in oracle sql

My table
loads(Unique) Value
T123 11
T234 9.5
T456 15
T678 35
T345 3.7
Want I want
count(values<=10) count(values>10 &<=20) count(values>20)
2 2 1
I tried to use CASE but don't know the usage
CASE yes; not with COUNT but with SUM:
SQL> with test (loads, value) as
2 (select 't123', 11 from dual union all
3 select 't234', 9.5 from dual union all
4 select 't456', 15 from dual union all
5 select 't678', 35 from dual union all
6 select 't345', 3.7 from dual
7 )
8 select
9 sum(case when value <= 10 then 1 end) cnt_1,
10 sum(case when value > 10 and value <= 20 then 1 end) cnt_2,
11 sum(case when value > 20 then 1 end) cnt_3
12 from test;
CNT_1 CNT_2 CNT_3
---------- ---------- ----------
2 2 1
SQL>
Use conditional aggregation as
select coalesce(sum(case when value<=10 then 1 end),0) as "values<=10",
coalesce(sum(case when value>10 and value<=20 then 1 end),0) as "values>10value<20",
coalesce(sum(case when value>20 then 1 end),0) as "values>20"
from your_table;

SQL query sum of total corresponding rows

I have two tables as below. Caseid from first table is referenced in second table along with accidents. What I am trying to get total different accidents for a case type. Below two tables I documented sample data and expected result.
Table case:
caseId CaseType
1 AB
2 AB
3 AB
4 CD
5 CD
6 DE
Table CaseAccidents:
AccidentId caseID AccidentRating
1 1 High
2 1 High
3 1 Medium
4 1 LOW
5 2 High
6 2 Medium
7 2 LOW
8 5 High
9 5 High
10 5 Medium
11 5 LOW
Result should look like:
CaseType TotalHIghrating TotalMediumRating TotalLOWRating
AB 3 2 2
CD 2 1 1
DE 0 0 0
To get the sum of every rating, you can Use a SUM(CASE WHEN) clause, adding 1 by every record that match the rating.
In your question, you have pointed out that you want to see all distinct CaseType, you can get it by using a RIGHT JOIN, this will include all records of case table.
select case.CaseType,
sum(case when caseAccidents.AccidentRating = 'High' then 1 else 0 end) as TotalHighRating,
sum(case when caseAccidents.AccidentRating = 'Medium' then 1 else 0 end) as TotalMediumRating,
sum(case when caseAccidents.AccidentRating = 'LOW' then 1 else 0 end) as TotalLowRating
from caseAccidents
right join case on case.caseId = caseAccidents.caseID
group by case.CaseType;
+----------+-----------------+-------------------+----------------+
| CaseType | TotalHighRating | TotalMediumRating | TotalLowRating |
+----------+-----------------+-------------------+----------------+
| AB | 3 | 2 | 2 |
+----------+-----------------+-------------------+----------------+
| CD | 2 | 1 | 1 |
+----------+-----------------+-------------------+----------------+
| DE | 0 | 0 | 0 |
+----------+-----------------+-------------------+----------------+
Check it: http://rextester.com/MCGJA9193
Have you use case in a select clause before?
select C.CaseType,
sum(case when CA.AccidentRating = 'High' then 1 else 0 end)
from Case C join CaseAccidents CA on C.CaseId = CA.CaseId
group by C.CaseType
Please see this. Sample query of the table and also that result
create table #case(caseid int,casetype varchar(5))
insert into #case (caseid,casetype)
select 1,'AB' union all
select 2,'AB' union all
select 3,'AB' union all
select 4,'CD' union all
select 5,'CD' union all
select 6,'DE'
create table #CaseAccidents(AccidentId int, CaseId int,AccidentRating varchar(10))
insert into #CaseAccidents(AccidentId, CaseId, AccidentRating)
select 1,1,'High' union all
select 2,1,'High' union all
select 3,1,'Medium' union all
select 4,1,'Low' union all
select 5,2,'High' union all
select 6,2,'Medium' union all
select 7,2,'Low' union all
select 8,5,'High' union all
select 9,5,'High' union all
select 10,5,'Medium' union all
select 11,5,'Low'
My script
select c.casetype,
sum(case when ca.AccidentRating='High' then 1 else 0 end) as TotalHighRating,
sum(case when ca.AccidentRating='Medium' then 1 else 0 end) as TotalMediumRating,
sum(case when ca.AccidentRating='Low' then 1 else 0 end) as TotalLowRating
from #case c
Left join #CaseAccidents ca
on c.Caseid=ca.Caseid
group by c.casetype
Hope This could help!
Another approach using Pivot operator
SELECT casetype,
[High],
[Medium],
[Low]
FROM (SELECT c.casetype,
AccidentRating
FROM case c
LEFT JOIN CaseAccidents ca
ON ca.CaseId = c.caseid)a
PIVOT (Count(AccidentRating)
FOR AccidentRating IN ([High],
[Medium],
[Low]) ) p
Try This code once.
select casetype,
sum(case when ca.AccidentRating='High' then 1 else 0 end ) as TotalHIghrating,
sum(case when ca.AccidentRating='Medium' then 1 else 0 end ) as TotalMediumRating ,
sum(case when ca.AccidentRating='Low' then 1 else 0 end ) as TotalLOWRating
from #case c
left join #CaseAccidents ca on c.caseid=ca.CaseId
group by casetype

Sub select & union all

SELECT C.ClientCaseNumber,
Sum(CASE
WHEN CA.CaseActionDefinitionId IN (28, 29, 30) THEN 1
ELSE 0
END) AS [Wezwania],
Sum(CASE
WHEN CA.CaseActionDefinitionId IN (14, 21) THEN 1
ELSE 0
END) AS [Kontakt],
Sum(CASE
WHEN CA.CaseActionDefinitionId = 32 THEN 1
ELSE 0
END) AS [SMS],
Sum(CASE
WHEN CA.CaseActionDefinitionId = 44 THEN 1
ELSE 0
END) AS [Zgon],
Sum(CASE
WHEN CA.CaseActionDefinitionId = 49 THEN 1
ELSE 0
END) AS [Areszt],
Sum(CASE
WHEN CA.CaseActionDefinitionId = 37 THEN 1
ELSE 0
END) AS [Odmowa],
Sum(CASE
WHEN CA.CaseActionDefinitionId = 39 THEN 1
ELSE 0
END) AS [Podważa],
Sum(CASE
WHEN CA.CaseActionDefinitionId = 99 THEN 1
ELSE 0
END) AS [Ugoda],
[Adres],
[Numer],
[Mail],
[Powód]
FROM (SELECT Notes AS [Adres]
FROM CaseActionHistory
WHERE CaseActionDefinitionId = 68
UNION ALL
SELECT Info AS [Numer]
FROM CaseActionHistory
WHERE CaseActionDefinitionId IN (54, 55, 56, 58,
59, 60, 61, 62, 63)
UNION ALL
SELECT Notes AS [Mail]
FROM CaseActionHistory
WHERE CaseActionDefinitionId = 66
UNION ALL
SELECT Description AS [Powód]
FROM CaseActionDefinition
JOIN CaseActionHistory AS C
ON DefinitionId = C.CaseActionDefinitionId
WHERE DefinitionId BETWEEN 70 AND 78) AS x
INNER JOIN CaseDetails AS C
ON x.CaseDetailId = C.CaseDetaislId
INNER JOIN CaseActionHistory AS CA
ON C.CaseDetailsId = CA.CaseDetailId
WHERE C.ClientId = '11'
GROUP BY C.ClientCaseNumber
I've got such query. As return shows error of invalid columns "CaseDetailId, CaseDetailsId, Mail, Numer, Powód".
http://oi39.tinypic.com/2vwy44n.jpg
That's more or less how the results should look like.
ClientCaseNumber is taken from table CaseDetails
All the sums are sums of code added to CaseActionHistory table.
Notes/Info are in CaseActionHistory table
Description is placed in CaseActionDefinition table.
Between tables there are such connections:
CaseDetails.CaseDetailId = CaseActionHistory.CaseDetailsId
CaseActionHistory.CaseActionDefinitionId = CaseActionDefinition.DefinitionId
The UNION clause does not work like that.
This query:
select Notes as [Adres] from CaseActionHistory where ...
UNION ALL
select Info as [Numer] from CaseActionHistory where ...
UNION ALL
select Notes as [Mail] from CaseActionHistory where ...
UNION ALL
select Description as [Powód] from CaseActionDefinition join CaseActionHistory ...
will not populate a table with 4 columns. Instead it will be a table with one column, with all the values one after the other. The name of the column will be taken from the first SELECT, i.e.
if the first query returns values 1 and 2,
the second query returns values 3 and 4
the third query returns values 5 and 6
the fourth query returns values 7 and 8
you wont get:
Adres | Numer | Mail | Powód
------------------------------
1 | 3 | 5 | 7
2 | 4 | 6 | 8
but you'll get:
Adres
-------
1
2
3
4
5
6
7
8
Are you not missing the alias 'x' from these fields:
SELECT
C.ClientCaseNumber
,sum(case when CA.CaseActionDefinitionId in (28,29,30) then 1 else 0 end) as [Wezwania]
,sum(case when CA.CaseActionDefinitionId in (14,21) then 1 else 0 end) as [Kontakt]
,sum(case when CA.CaseActionDefinitionId = 32 then 1 else 0 end) as [SMS]
,sum(case when CA.CaseActionDefinitionId = 44 then 1 else 0 end) as [Zgon]
,sum(case when CA.CaseActionDefinitionId = 49 then 1 else 0 end) as [Areszt]
,sum(case when CA.CaseActionDefinitionId = 37 then 1 else 0 end) as [Odmowa]
,sum(case when CA.CaseActionDefinitionId = 39 then 1 else 0 end) as [Podważa]
,sum(case when CA.CaseActionDefinitionId = 99 then 1 else 0 end) as [Ugoda]
,x.[Adres]
,x.[Numer]
,x.[Mail]
,x.[Powód]
FROM
(select Notes as [Adres] from CaseActionHistory where CaseActionDefinitionId = 68
UNION ALL
select Info as [Numer] from CaseActionHistory where CaseActionDefinitionId in (54,55,56,58,59,60,61,62,63)
UNION ALL
select Notes as [Mail] from CaseActionHistory where CaseActionDefinitionId = 66
UNION ALL
select Description as [Powód] from CaseActionDefinition join CaseActionHistory as C on DefinitionId = C.CaseActionDefinitionId where DefinitionId between 70 and 78)
AS x
inner join CaseDetails as C on x.CaseDetailId = C.CaseDetaislId
inner join CaseActionHistory as CA on C.CaseDetailsId = CA.CaseDetailId
where C.ClientId = '11'
GROUP by C.ClientCaseNumber

Group by in Subquery

I have a table AssignmentMaster in that I have following columns with data
AssignmentID PaidAmount RefundAmount UserID
1 20 0 1
2 10 5 1
3 30 7 2
4 25 0 3
5 35 15 3
6 10 3 1
7 5 0 3
8 10 0 3
Now I want to find out the TotalNumberofAssignment with respect to userID, i.e. result should be:
UserID TotalAssignment TotalAssignmentofRefundAmount TotalPaidAmount TotalRefundAmount
1 3 2 40 8
2 1 1 30 7
3 4 1 75 15
How I can get above given result in MSSQL.
your any help will help me lot.
SELECT
UserID,
COUNT(AssignmentID) AS TotalAssignment,
SUM(SIGN(RefundAmount)) AS TotalAssignmentofRefundAmount,
SUM(PaidAmount) AS TotalPaidAmount,
SUM(RefundAmount) AS TotalRefundAmount
FROM
MyTable
GROUP BY
UserID
Note:
SIGN(RefundAmount) works if RefundAmount is always >= 0.
If not, change to
SUM(CASE WHEN RefundAmount <> 0 THEN 1 ELSE 0 END) AS TotalAssignmentofRefundAmount
Select UserID,
count(1) as TotalAssignment,
sum( case when RefundAmount = 0 then 0 else 1 end) as TotalAssignmentofRefundAmount,
sum(PaidAmount) as TotalPaidAmount ,
sum(RefundAmount) as TotalRefundAmount
From AssignmentMaster
Group by UserID
To show how to do this using nested SQL:
Select UserTotals.UserID, UserTotals.TotalAssignment,
Refunds.TotalAssignmentofRefundAmount,
UserTotals.TotalPaidAmount, UserTotals.TotalRefundAmount
From (select UserID,
Count(AssignmentID) [TotalAssignment],
Sum(PaidAmount) [TotalPaidAmount],
sum(RefundAmount) [TotalRefundAmount]
From #AssignmentMaster
Group By UserID
) [UserTotals] Left Join
(Select UserID,
Count(AssignmentID) [TotalAssignmentofRefundAmount]
From #AssignmentMaster
Where RefundAmount > 0
Group By UserID
) [Refunds] On Refunds.UserID = UserTotals.UserID
select UserId, count (AssignmentID) as TotalAssignment,
sum(case when RefundAmount = 0 then 0 else 1 end) as TotalAssignmentofRefundAmount,
sum(PaidAmount) as TotalPaidAmound,
sum(RefundAmount) as TotalRefundAmount
from AssignmentMaster
group by UserID;