Sql query without sub query and joins - mysql

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

Related

Reject database table items using condition in SQL database

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')

Mysql count(*) based in two relations

I would like to count(*) how much customers have created a post or made a comment. If the same customer has made several posts and comments, it should count only once.
Customer Table:
ID Name ...
1 Jonh
2 Mark
3 King
4 Doe
Post Table:
ID USER_ID...
1 1
2 1
3 3
4 1
Comment Table:
ID USER_ID...
1 1
2 3
3 3
4 4
It should return count(*) = 3
(user_id: 1, 3 and 4).
Try this one. It worked for me and returns what you're looking for:
SELECT COUNT( USER_ID ) AS TOTAL
FROM (
SELECT USER_ID
FROM POSTS
UNION
SELECT USER_ID
FROM COMMENTS
)X
I used POSTS and COMMENTS as table names bc I was unsure what your exact table names are, so make sure to change these in your query.
This should work:
SELECT COUNT(DISTINCT USER_ID) FROM (
SELECT USER_ID FROM POST_TABLE
UNION
SELECT USER_ID FROM COMMENT_TABLE
)

mysql - do not display data if a certain condition is met

Sorry I don't really know how to make a title for this because I can't explain it really. for example i have here a table
c_id emp_id clinic_id
1 1 1
2 1 2
3 2 1
4 3 3
5 1 3
now i will do a query like this
select distinct * from table where clinic_id <> 1
And the result would be
c_id emp_id clinic_id
2 1 2
4 3 3
5 1 3
at this point I need help, if from the where clinic_id <> 1 a certain emp_id is within its row of condition(Sorry for my bad english). for example emp_id 1. All emp_id 1 must not be display also.
So the result would be just
c_id emp_id clinic_id
4 3 3 // *The result I want*
You can use NOT EXISTS for this:
select distinct *
from mytable as t1
where clinic_id <> 1 and
not exists (select 1
from mytable as t2
where t1.emp_id = t2.emp_id and t2.clinic_id = 1)
For the result you're looking for, wouldn't something like this be simpler?
SELECT DISTINCT * FROM table WHERE clinic_id !=1 AND emp_id !=1
Here we're saying we want any clinic_id that is not 1 and any emp_id that is also not 1.
Since you're dealing with PHP, then you would simply substitute the numbers for the variables you're trying to not match.
SELECT DISTINCT * FROM table WHERE clinic_id !=$session_variable AND emp_id !=$some_value
SELECT DISTINCT *
FROM table
WHERE clinic_id <> 1
AND emp_id NOT IN
(SELECT DISTINCT emp_id
FROM table
WHERE clinic_id = 1)
Try this one.
It uses the subquery to return the emp_ids which are in the same row as the 1 in the column clinic_id, and removes them from the resultset because you also don't want those emo_ids.
Also you could use a GROUP BY clause instead of DISTINCT. Usually GROUP BY would be turned into a distinct by the database if you are not using any aggregate functions, but sometimes they behave differently. If you are interested in this topic you can also see this question: Is there any difference between GROUP BY and DISTINCT
SELECT c_id, emp_id, clinic_id
FROM clinics
WHERE clinic_id <> 1
AND emp_id NOT IN
(SELECT DISTINCT emp_id
FROM clinics
WHERE clinic_id = 1)
GROUP BY c_id, emp_id, clinic_id;

Mysql sum restult from a query

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

How can I select classmates of a given student from a student-class association table?

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