This is my database
studentId
course
grade
1
CSE115
F
2
CSE115
C
3
CSE115
A
3
EEE111
B
2
EEE111
F
1
EEE111
B
I want to execute a query that will only return the 'studentId' who has not failed in any course(No 'F' with the studentId in the table). In my example table I have showed only two courses(CSE115,EEE111) but in my case it can be 30 courses and only those student will be selected who has passed in all the courses given to the table. If a student passed in 29 courses except 1 course he will not be selected.
For example in the given table the output will be,
Output:
studentId
course
grade
3
CSE115
A
3
EEE111
B
Can anyone help me building the query?
You can get all the studentIds that failed at least once with this query:
SELECT studentId FROM tablename WHERE grade = 'F'
Use it with NOT IN to get the rows that you want:
SELECT *
FROM tablename
WHERE studentId NOT IN (SELECT studentId FROM tablename WHERE grade = 'F')
Or with NOT EXISTS:
SELECT t.*
FROM tablename t
WHERE NOT EXISTS (SELECT 1 FROM tablename tt WHERE tt.studentId = t.studentId AND grade = 'F')
Related
Suppose I have a table t1 with two columns, Student_ID and Grade. The data shown like this;
Student_ID, Grade (1,'A'),(1,'C'),(1,'F'),(1,'A'),(2,'B'),(2,'A'),(2,'C'),(2,'A').
Now I have to group the Student_ID with a new column named 'Result'. Student_ID 1 have one grade 'F' so consider failed and Student_ID 2 have no 'F' grade so consider passed. Require result should be like this.
Student_ID Result
1 Failed
2 Passed
Because the table have 500 records so can not manually enter 'Passed" or 'Failed'.
SELECT `Student_ID`, (IF(`Grade`='F',"Failed","Passed")) AS `Result`
FROM t1 group by `Student_ID`;
Above code will not work as the column Grade has 4 values not 1.
So code will be some thing like this.
SELECT `Student_ID`, (IF(`Grade` CONTAINS 'F',"Failed","Passed")) AS `Result` FROM t1 group by `Student_ID`;
There is no such thing CONTAINS in sql but may be HAVING or IN but how to use them here?
You can use CASE statement with EXISTS:
select DISTINCT
t.Student_ID,
case
when exists (
select 1 from t1 where Student_ID = t.Student_ID and Grade = 'F'
) then 'Failed'
else 'Passed'
end Result
from t1 t
See the demo.
Results:
| Student_ID | Result |
| ---------- | ------ |
| 1 | Failed |
| 2 | Passed |
You can also do it by evaluating each Grade to 1 or 0 for 'F' or not 'F' and then grouping by Student_ID:
select
t.Student_ID,
case sum(t.Result)
when 0 then 'Passed'
else 'Failed'
end Result
from (select Student_ID, Grade = 'F' Result from t1) t
group by t.Student_ID
See the demo.
I have this table of a database:
cou_id | cou_tea_1 | cou_tea_2 | cou tea_3
1 1 1 2
2 2 1 1
3 4 1 1
Each course has an id, and cou_tea_1, cou_tea_2, cou tes_3 has the teacher that teaches in the lesson 1 of the course, lesson 2 and lesson 3.
In this example in the course 1 the first lesson was made by the teacher 1, the second by the teacher 1 and the third by the teacher 2.
I need a query that gives me the number of the teacher and the total of the lessons he made, in this example:
teacher | total_lesson_number
1 6
2 2
4 1
This is a very poor table design. In general, when you have multiple columns with the same name, you are storing values in columns. These should be in a row.
What you need to do is unpivot the data and then aggregate:
select teacher, count(*) as total_lesson_number
from (select cou_tea_1 as teacher from t union all
select cou_tea_2 from t union all
select cou_tea_3 from t union all
select cou_tea_4 from t
) t
group by teacher;
After getting this to work, you should study up on junction tables so you know the right way to store such data in a relational database.
You can use UNION ALL to unpivot the table, then GROUP BY the teacher id:
SELECT teacher, COUNT(*) AS total_lesson_number
FROM (
SELECT cou_id, cou_tea_1 AS teacher
FROM mytable
UNION ALL
SELECT cou_id, cou_tea_2
FROM mytable
UNION ALL
SELECT cou_id, cou tea_3
FROM mytable) AS t
GROUP BY teacher
Not a new idea I did not want to discard...
select teacher, sum(n) as total_lesson_number from (
(select cou_tea_1 as teacher, count (*) as n from course group by cou_tea_1)
union all
(select cou_tea_2 as teacher, count (*) as n from course group by cou_tea_2)
union all
(select cou_tea_3 as teacher, count (*) as n from course group by cou_tea_3)
)
group by teacher
To have students (student_id, course_id, course_name) who take exactly only one course, using a simple SQL statement with no sub-query and no join at all
student_id course_id course_name
---------------------------------------------
1 1000 'CS 101'
2 1000 'CS 101'
1 2000 'CHEM 200'
2 3000 'ENG 211'
3 1000 'CS 101'
4 5000 'Bio 400'
Any one please me on this. Tried many approaches but couldn't get the answer without sub query.
It is possible to retrieve just the STUDENT_ID for students on just one course:
SQL> SELECT student_id
2 FROM students
3 GROUP BY student_id
4 HAVING COUNT(course_id) = 1
5 /
STUDENT_ID
----------
4
3
Elapsed: 00:00:00.09
SQL>
But to get additional information, such as the course name, then we need to use a sub-query or join.
Use group by with having
select student_id,count(course_id) as num
from students group by student_id
having num =1
or this :-
select student_id
from students group by student_id
having count(course_id) =1
How about using GROUP BY and HAVING COUNT
SELECT student_id, course_name FROM students
GROUP BY student_id, course_name
HAVING COUNT(course_id) = 1
I have a table where I can store the same name with different states.
|ID|name|state
1 A 1
2 A 2
3 B 3
4 C 1
There 3 states 1,2,3.
How can I find those records which has no state 3, maximum 2?
In this example A and C has no state 3 so they would be the result of the query:
SELECT * FROM `records` WHERE (`state_id`!=3)
It only returns rows without state 3 but it can be that value.
http://www.sqlfiddle.com/#!9/35dbe/2
SELECT r.*
FROM `records` r
LEFT JOIN `records` r3
ON r.name = r3.name
AND r3.state=3
WHERE r3.state IS NULL
How about a DISTINCT and NOT IN?
Something like
SELECT DISTINCT Name
FROM Table1 t
WHERE Name NOT IN (
SELECT Name
FROM Table1 s
WHERE s.State = 3)
SQL Fiddle DEMO
You can do this with conditional aggregation:
select name from t
group by name
having sum(case when state = 3 then 1 else 0 end) = 0
Fiddle http://sqlfiddle.com/#!9/a8bb5/2
If my table looks like the following, how can I select classmates of a given student?
student_class_assn
student_id class_id
1 1
2 1
3 1
4 2
5 2
6 3
For example, Student 1 has students 2 and 3 as classmates.
Please help me write a query that pivots on the known student_id and selects only the classmates (and not including the given student).
Here is an example using a sub-select. But can you help me write it with joins instead?
SET #KNOWN_STUDENT=1;
SELECT
student_id
FROM
student_class_assn
WHERE
class_id IN (
SELECT class_id FROM student_class_assn WHERE student_id = #KNOWN_STUDENT
)
AND student_id != #KNOWN_STUDENT;
Given my table above I expect the following results for each given student_id:
1 returns 2,3
2 returns 1,3
3 returns 1,2
4 returns 5
5 returns 4
6 returns NULL
all you need to do is just join the table and pass a conditional
SELECT t1.student_id
FROM student_class_assn t
JOIN student_class_assn t1
ON t1.class_id = t.student_id
AND t1.student_id <> 1
WHERE t.student_id = 1
FIDDLE
This will not show students with no classmates:
select s1.sid,group_concat(s2.sid order by s2.sid,',')
from
stud_class s1 inner join
stud_class s2 on s1.cid=s2.cid
where s1.sid <> s2.sid
group by s1.sid
order by 1