I have a table like this.
Id Name Test Subject Marks
----------------------------
1 Alex 1 Maths 40
1 Alex 2 Maths 80
1 Alex 1 Sociology 55
1 Alex 2 Sociology 70
1 Alex 3 Sociology 60
2 Mark 1 Maths 30
2 Mark 2 Maths 60
2 Mark 1 Sociology 40
2 Mark 2 Sociology 50
2 Mark 3 Sociology 30
What I need is a group by on Id, Name, Subject and sum(Marks) in a single row, to give a result like:
Id Name Maths Sociology
-----------------------
1 Alex 120 185
2 Mark 90 120
I can get this as:
Id Name Marks
--------------
1 Alex 120
2 Mark 90
or:
Id Name Marks
-------------
1 Alex 185
2 Mark 120
I tried multiple options but I'm getting multiple rows for each ID.
The query below is not working:
select
Id, Name, Sum(Marks) where Subject = 'Maths' as Maths,Sum(Marks ) where Subject = 'Sociology' as Sociology
from
Table
group by
Id, Name;
I get this error:
"Error while compiling statement: FAILED: ParseException line 3:66 missing EOF at 'as' near ''Maths''
You are looking for PIVOT. Try :
create table #tbl(Id int, Name varchar(20), Test int, Subject varchar(20), Marks int)
insert into #tbl values
(1,'Alex',1,'Maths', 40 ),
(1,'Alex',2,'Maths', 80 ),
(1,'Alex',1,'Sociology', 55),
(1,'Alex',2,'Sociology', 70),
(1,'Alex',3,'Sociology', 60),
(2,'Mark',1,'Maths', 30 ),
(2,'Mark',2,'Maths', 60 ),
(2,'Mark',1,'Sociology', 40),
(2,'Mark',2,'Sociology', 50),
(2,'Mark',3,'Sociology', 30)
--select * from #tbl
SELECT ID,Name,Maths,Sociology
FROM(
SELECT ID, Name, Subject, Marks
FROM #tbl
) tbl
PIVOT(
SUM(Marks) FOR Subject IN (Maths, Sociology)
) piv
output:
ID Name Maths Sociology
----------- ---- ------------ -----------
1 Alex 120 185
2 Mark 90 120
You can use a case expression to effectively filter the values going into your sum:
select Id
,Name
,sum(case when Subject = 'Maths' then Marks else 0 end) as Maths
,sum(case when Subject = 'Sociology' then Marks else 0 end) as Sociology
from Table
group by Id
,Name;
If you are looking to do this across a lot of different subject values however, you will need to look at using pivot:
select Id
,[Name]
,[Maths]
,[Sociology]
from (select Id, [Name], [Subject], Marks from #t) as t
pivot(sum(Marks)
for [Subject] in(Maths,Sociology)
) as p;
Another solution using PIVOT operator:
SELECT
ID
,Name
,Maths
,Sociology
FROM(
SELECT
ID
,Name
,Subject
,Marks
FROM your_table
) tbl
PIVOT(
SUM(Marks) FOR Subject IN (Maths, Sociology)
) pvt
You can use below query :
select id,name,maths_marks,sociology_marks
from
(select id,name,test,subject,marks
from table)
pivot(sum(marks) for subject in ('Maths' as Maths_marks,'Sociology' as Sociology_marks);
Related
Select name, Subject, Score from Class
Tables
name | Subject | Score
-----------------------
Ola maths 20
Ola pop 15
Ola eng 74
Dodo maths 21
Dodo pop 19
Dodo eng 54
Please any idea on how to make it display like this:
name | Subject | Score
-----------------------
Ola maths 20
pop 15
eng 74
Dodo maths 21
pop 19
eng 54
Please any assistant will be appreciated
if you absolutely have to do this in SQL:
with cte as
(
select rn=row_number() over (partition by name order by 1)
,*
from [table]
)
select n = case when rn=1 then name else '' end, Subject, Score
from cte
order by name,rn
But if you do this then you are losing the ability to use this data again.
As previous people have already comment, this might not be your best approach but the following query returns your expected result:
create table Class (Name varchar(10), Subject varchar(10), Score int)
insert into Class
values ('Ola', 'maths', 20),
('Ola', 'pop', 15),
('Ola', 'eng', 15),
('Dodo', 'maths', 20),
('Dodo', 'pop', 15),
('Dodo', 'eng', 15)
select
case when Row# = 1 then t.Name else null end,
Subject,
Score
from (
select
ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Name ASC) AS Row#,
Name,
Subject,
Score
from Class) t
drop table Class
Hi all I am quite new to SQL. I have a table (TABLE1) with two columns as below
Name age
--------
jim 18
jim 21
dave 18
dave 18
john 23
john 41
I need to create a view in SSMS which lists distinct ages for each name in a separate column as below
Jim Dave John
---------------
18 18 23
21 41
I have tried a sub query like
SELECT DISTINCT AGE FROM TABLE1 WHERE NAME = JIM
But I encountered a sub query cannot return more than one value.
You can use row_number() & do aggregation :
select max(case when name = 'jim' then age end) as jim,
max(case when name = 'dave' then age end) as dave,
max(case when name = 'john' then age end) as john
from (select t.*, row_number() over (partition by name order by age) as seq
from table t
) t
group by seq;
I've a table like this:
STU_NAME SUBJECT MARKS
--------- --------- ------
1 ENGLISH 90
1 TAMIL 80
1 MATHS 70
2 MATHS 70
2 TAMIL 80
2 ENGLISH 95
And the result should be like below:
STU_NAME MATHS_MARK ENGLISH_MARK TAMIL_MARK TOTAL_MARKS
--------- ----------- ------------ ----------- -------------
1 70 90 80 240
2 70 95 80 245
Can we achieve this with a query?
I find that the easiest way is to use conditional aggregation:
select stu_name,
max(case when subject = 'MATHS' then Marks end) as Maths,
max(case when subject = 'ENGLISH' then Marks end) as English,
max(case when subject = 'TAMIL' then Marks end) as Tamil,
sum(Marks) as Total
from t
group by stu_name;
I got the same using PIVOT function.,
SELECT *
FROM (SELECT *
FROM x)
PIVOT (MAX(marks) FOR (SUBJECT) IN ('ENGLISH', 'MATHS', 'TAMIL'));
But, Still I'm facing few issues.,
whether it is possible to get sum(marks) while using PIVOT.
And getting subjects with respective marks without mentioning every subject(when we do know what are the subjects will be) in both(case,pivot).,?
I have a table abc which have many records with columns col1,col2,col3,
dept | name | marks |
science abc 50
science cvv 21
science cvv 22
maths def 60
maths abc 21
maths def 62
maths ddd 90
I need to order by dept and name with ranking as ddd- 1, cvv - 2, abc -3, else 4 then need to find out maximum mark of an individual. Expected result is
dept | name | marks |
science cvv 22
science abc 50
maths ddd 90
maths abc 21
maths def 62
. How may I do it.?
SELECT
dept,
name,
MAX(marks) AS mark
FROM
yourTable
GROUP BY
dept,
name
ORDER BY
CASE WHEN name = 'ddd' THEN 1
name = 'cvv' THEN 2
name = 'abc' THEN 3
ELSE 4 END
Or, preferably, have another table that includes the sorting order.
SELECT
yourTable.dept,
yourTable.name,
MAX(yourTable.marks) AS mark
FROM
yourTable
INNER JOIN
anotherTable
ON yourTable.name = anotherTable.name
GROUP BY
yourTable.dept,
youtTable.name
ORDER BY
anotherTable.sortingOrder
This should work:
SELECT Dept, Name, MAX(marks) AS mark
FROM yourTable
GROUP BY Dept, Name
ORDER BY CASE WHEN Name = 'ddd' THEN 1
WHEN Name = 'cvv' THEN 2
WHEN Name = 'ABC' THEN 3
ELSE 4 END
I have a table of bank staff information that looks like this:
branchNumber Position firstName lastName staffNumber
------------ -------- --------- -------- -----------
25 Manager john doe 11111
25 Secretary robert paulson 11112
25 Secretary cindy lu 11113
66 Manager tim timson 22223
66 Manager jacob jacobson 22224
66 Secretary henry henryson 22225
66 Supervisor paul paulerton 22226
I am actually done with this, but I completed the assignment using SQL common table expressions, and I can't use them in this project, I need them in this format.
branchNumber numOfManagers numOfSecretaries numOfSupervisors totalEmployees
------------ ------------- ---------------- ---------------- --------------
25 1 2 0 3
66 2 1 1 4
My issue is getting multiple columns with information from a row, I have this so far,
SELECT branchNumber, COUNT(*) AS numOfManagers
FROM Staff
WHERE position = 'Manager'
GROUP BY branchNumber, Position;
This outputs the correct information for numOfManagers, but making the next three columns eludes me without using CTE's. I tried sub selects too, with no luck. Anybody have any ideas?
You can use something like this:
select branchnumber,
sum(case when Position ='Manager' then 1 else 0 end) numofManagers,
sum(case when Position ='Secretary' then 1 else 0 end) numofSecretaries,
sum(case when Position ='Supervisor' then 1 else 0 end) numofSupervisors,
count(*) totalEmployees
from yourtable
group by branchnumber
See SQL Fiddle with Demo
Or you can use the PIVOT function:
select branchnumber,
'Manager', 'Secretary', 'Supervisor',
TotalEmployees
from
(
select t1.branchnumber,
t1.position,
t2.TotalEmployees
from yourtable t1
inner join
(
select branchnumber, count(*) TotalEmployees
from yourtable
group by branchnumber
) t2
on t1.branchnumber = t2.branchnumber
) x
pivot
(
count(position)
for position in ('Manager', 'Secretary', 'Supervisor')
) p;
See SQL Fiddle with Demo