How can i turn a table from this form:
S_ID SUBJECT MARK
1 English 90
1 Math 40
1 Computer 30
2 English 85
2 Math 10
2 Computer 06
3 English 10
3 Math 20
3 Computer 40
To this form
S_ID English Math Computer
1 90 40 30
2 85 10 06
3 10 20 40
using SQL code,
I'm using MS Access 2010,
Thank you
SELECT S_ID ,
MAX(CASE WHEN subject = 'English' THEN mark ELSE null END) AS English,
MAX(CASE WHEN subject = 'Math' THEN mark ELSE null END) AS Math,
MAX(CASE WHEN subject = 'Computer' THEN mark ELSE null END) AS Computer
FROM myTable
GROUP BY S_ID
You want a cross-tab query which will yield a column per subject;
TRANSFORM Sum(MARK) AS TotalMark
SELECT
S_ID
FROM marks
GROUP BY S_ID
PIVOT SUBJECT;
if this is a one time exercise, you could use many statements, sequentially: something like this:
insert into new_table
select distinct s_id, 0,0,0
from old_table
then a series of updates
update new_table n
set english = (select english from old_table where s_id = n.s_id )
where s_id = n.s_id
Related
I have a table called assignment:
assignment_id student_id report_id
--------------------------------------
25 1 0
56 2 10
28 1 5
94 1 0
75 1 0
86 1 0
95 2 5
I'm using this SQL query to find out total number of assignment received by each student
select student_id as student, count(assignment_id) as total_assignment ,
from assignment
group by student_id
order by student_id asc
Result of this query is
student total_assignment
---------------------------
1 5
2 2
In assignment table where report_id == 0, assignment is pending otherwise assignment is disposed. I need to also find total disposed and pending assignment by each student.
Please help me complete this above SQL query. Thanks
Just use conditional aggregation:
select student_id as student, count(*) as total_assignment,
sum(case when report_id = 0 then 1 else 0 end) as num_pending,
sum(case when report_id <> 0 then 1 else 0 end) as num_completed
from assignment
group by student_id
order by student_id asc;
As a matter of word choice: I prefer "completed" to "disposed". At least in American English, "disposed" has the connotation of being thrown out as garbage.
I am trying to query set result set which returns something like the below.
I need to return only 1 row per name and need to GROUP BY but only the name that have a value of '8' under the Grade column are desired. The below is a result from another query. Because Sandra has a different value other than 8, Sandra should be omitted.
eg:- In the below I need to get one row for John only.
Please advise. Thank you.
Name Grade
======= =====
Sandra 8
Sandra 8
Sandra 8
Sandra 9
John 8
John 8
John 8
John 8
Expected Result - 1 row
Name Grade
John 8
Aggregate your table on the name, and then use a HAVING clause to filter out names which have a grade other than 8 (or any other values which you do not want).
SELECT name, MIN(grade) AS grade
FROM yourTable
GROUP BY name
HAVING SUM(CASE WHEN grade <> 8 THEN 1 ELSE 0 END) = 0;
Demo
Update:
If the grade column were text, and you wanted to compare against the string '8' instead of a number, then you could use this HAVING clause:
HAVING SUM(CASE WHEN grade <> '8' THEN 1 ELSE 0 END) = 0;
If you want names that have only 8s, you can do:
select name
from t
group by name
having min(grade) = max(grade) and min(grade) = 8;
Alternately,
SELECT DISTINCT B.name, B.grade
FROM
(
SELECT name FROM yourTable GROUP BY name HAVING COUNT(DISTINCT grade) = 1
) Z
INNER JOIN
yourTable B
ON Z.name = B.name
AND B.grade = 8;
Let's say I have the following student data:
classroom gender student_id
-------------------------------------
First Grade M 123
First Grade F 124
First Grade F 125
Second Grade M 126
Third Grade M 127
...
I want to produce the following result: top 3 biggest classrooms ordered by total number of students with detail for each:
classroom boys_count girls_count total_count
--------------------------------------------------
Third Grade 30 30 60
First Grade 20 5 25
Fourth Grade 10 10 20
How can I do that in sql ? If necessary, I can use specific postrges features.
What I tried so far:
SELECT count(*) as total_count
, gender
, classroom
ORDER BY 1
GROUP BY classroom, gender
LIMIT 3
Then I re-organise results in some scripting language. But this is too slow. I want to have the correct results with one query
select classroom as name,
sum(case when gender = 'M' then 1 else 0 end) as boys_count,
sum(case when gender = 'F' then 1 else 0 end) as girls_count,
count(*) as total_count
from your_table
group by classroom
order by count(*) desc
limit 3
I want to change column name and value depending on condition.
My table is..
Roll Name Mark
3 Chaity 87
1 Anis 75
4 Unknown 30
2 Badol 0
And I want to get like this
Roll Name Grade
3 Chaity A+
1 Anis A
4 Unknown F
2 Badol F
Where Mark and Grade mapping is as follows:
0 to 60 is F
61 to 79 is A
80 and above is A+
A simple CASE expression will do it:
SELECT
Roll,
Name,
Grade = CASE
WHEN Mark <= 60 THEN 'F'
WHEN Mark <= 79 THEN 'A'
ELSE 'A+'
END
FROM tbl
ONLINE DEMO
you can use CASE WHEN ... or create a Grade table
SELECT Roll, Name, Grade = case when Mark >= 80 then 'A+'
when Mark between 61 and 79 then 'A'
else 'F'
end
FROM yourtable
using a Grade table
SELECT t.Roll, t.Name, g.Grade
FROM yourtable t
outer apply
(
select x.Grade
from GradeTable x
where t.Mark between x.Mark_from and x.Mark_to
) g
But isn't the grading system a bit drastic ? You either get an A or failed :(
I have A table of students and their grades.
How can I count the number of failed grades (<50)
and find the general average ( I mean the average for every student ) using sqlite?
this is the table (studentTable):
sID LessonID grade
1 1 45
1 2 50
1 3 65
2 1 44
2 2 22
2 3 91
I expect the results like this:
sID noOfFails Average
1 1 53
2 2 5
Try
SELECT
sID,
SUM(CASE WHEN grade < 50 THEN 1 ELSE 0 END) AS noOfFails,
AVG(grade) AS Average
FROM studentTable
GROUP BY sID
Demo at http://sqlfiddle.com/#!5/fcd13/1
You could use a case expression inside the count function:
SELECT sID, COUNT(CASE WHEN grade < 50 THEN 1 END) AS noOfFails, AVG(grade)
FROM mytable
You can simply run it as follows:
SELECT sID, COUNT(IIF(grade<50,1,NULL)) as noOfFails, AVG(grade) as Average
FROM studentTable GROUP BY sID