SQL select by qualifying multiple strings - mysql

I have to find student names who are enrolled in a class AND also in another class. But when I do a WHERE statement it cuts out out all the other lines that have the other classes.
So my question is: How would I go about doing it so that it compares the entire group and only selects students that are both in CLASSA and CLASSB.
Some of the students are in CLASSA and some of them are in CLASSB and some are in both. How do I get the one that is in both?
For example:
John Smith is in CLASSA
BETTY WHITE is in CLASSB
Timmy Edwards is in CLASSA
Timmy Edwards is in CLASSB
If I use an OR, it will select all of the names. But I only want a student that is in BOTH classes. So Timmy Edwards is the one I want selected.
WHERE C.DESCRIPTION LIKE 'Systems Analysis%'
AND C.DESCRIPTION LIKE 'Project Management%'

You can do use group by and having:
select student
from enrollments
where class in ('CLASSA', 'CLASSB')
group by student
having count(*) = 2;
This version assumes that a student can be enrolled only once for a given class.

No individual row will every have information for both classes. That means that AND and OR as you're using them are useless. You need to check for the existence of such rows using the EXISTS keyword.
select distinct
student
from
enrollments
where
exists (
select
1
from
enrollments e1
where
e1.student = enrollments.student
and e1.class = 'CLASSA'
) and exists (
select
1
from
enrollments e2
where
e2.student = enrollments.student
and e2.class = 'CLASSB'
)
Note:
Each row will have the student name in it, so I've added the DISTINCT keyword to remove the duplicates.

You could try something like this, (although im not sure what exactly your schema is like...)
WITH a AS
(
SELECT
S.FIRST_NAME||' '||S.LAST_NAME [Student]
,C.DESCRIPTION
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)
WHERE C.DESCRIPTION = 'CourseA'
)
,b AS
(
SELECT
S.FIRST_NAME||' '||S.LAST_NAME [Student]
,C.DESCRIPTION
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)
WHERE C.DESCRIPTION = 'CourseB'
)
Select a.Student, a.Description [DescA], b.Description [DescB]
from a join b on a.Student = b.Student
--optional where to just get students in both classes...
where a.Description is not null and b.Description is not null
Hope this assists...

You can always try the neat trick of joining a SELECT result with itself and then selecting from that result.
SELECT A.NAME
FROM (SELECT S.FIRST_NAME||' '||S.LAST_NAME as NAME,
S.STUDENT_ID as S_ID,
C.DESCRIPTION as DESC
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)) A
JOIN (S.STUDENT_ID as S_ID, C.DESCRIPTION as DESC
FROM STUDENT S
JOIN ENROLLMENT E ON (E.STUDENT_ID = S.STUDENT_ID)
JOIN SECTION SE ON (SE.SECTION_ID = E.SECTION_ID)
JOIN COURSE C ON (C.COURSE_NO = SE.COURSE_NO)) B
ON A.S_ID = B.S_ID
WHERE A.DESC LIKE 'Systems Analysis%'
AND B.DESC LIKE 'Project Management%'
GROUP BY A.NAME

Related

MySQL, count total numbers of each IDs in two or more tables

I have 3 individual students (table_student), each student have attended 3 classes (table_class_1, table_class_2, table_class_3)
Image below are the list of student table (table_student), class 1 (table_class_1), class 2 (table_class_2) and class 3 (table_class_3) together with the total result of each of the class table.
My goal is to count how many times each students has entered each of the classes. So my expected result would be as shown as image below
What I can do so far was using union but the result is not what i expected to be
SELECT COUNT(B.student_id) AS count_class_1, NULL, NULL FROM table_student A
INNER JOIN table_class_1 B ON A.id = B.student_id
WHERE B.student_id = 1
UNION
SELECT NULL, COUNT(B.student_id) AS count_class_2, NULL FROM table_student A
INNER JOIN table_class_2 B ON A.id = B.student_id
WHERE B.student_id = 1
UNION
SELECT NULL, NULL, COUNT(B.student_id) AS count_class_3 FROM table_student A
INNER JOIN table_class_3 B ON A.id = B.student_id
WHERE B.student_id = 1
Your tables are not normalized correctly which is part of the reason you are facing this challenge. Have three tables as follows:
table_student (id, student_name),
table_class (id, class_name),
table_student_class(id, table_student_id, table_class_id)
Populate the data to the tables and to get the student attendance count use the following statement.
select table_student_id, table_class_id, Count(id) as class_count
from table_student_class
group by table_student_id, table_class_id
The results will be a class attendance count for each student.
I would recomend having one table for classes.
But what you whant is possible too:
SELECT
ts.id,
ts.student_name,
(SELECT COUNT(*) FROM table_class_1 tc1 WHERE tc1.student_id = ts.id) c1,
(SELECT COUNT(*) FROM table_class_2 tc2 WHERE tc2.student_id = ts.id) c2,
(SELECT COUNT(*) FROM table_class_3 tc3 WHERE tc3.student_id = ts.id) c3
FROM
table_student ts
ORDER BY
ts.student_name
;

SQL "GROUP BY" and "INNER JOIN" Statements together

I have two tables of ANIMAL and NEED:
ANIMAL NEED
Name Species Birthday A_Species Type
Koala1 Phascolarctidae 02-10-2014 Phascolarctidae Veg.
Bear1 Ursinae 03-10-2016 Ursinae Veg.
Koala2 Phascolarctidae 04-09-2015 Ursinae Meet
Cattle1 Bovidae 20.03.2017 Ursinae Fish
Whale1 Cetacea 08.05.2010 Bovidae Veg.
Cetacea Fish
I would like to select the following table
Name Type
Koala1 Veg.
Koala2 Veg.
Cattle1 Veg.
Whale1 Fish
which is the list of name of animal and their food that needs only one type of food!
I have to combine two statement of
SELECT A_Species
FROM NEED GROUP BY A_Species
HAVING COUNT(A_Species)=1;
and
SELECT ANIMAL.NAME, NEED.Type
FROM ANIMAL
INNER JOIN NEED ON ANIMAL.Species = NEED.A_Species;
I tried
SELECT ANIMAL.NAME, NEED.Type
FROM ANIMAL
INNER JOIN NEED ON ANIMAL.Species = NEED.A_Species
WHERE EXISTS(SELECT A_Species
FROM NEED GROUP BY A_Species
HAVING COUNT(A_Species)=1);
which it is not working!
Can you help me how can I put them together?
One method uses aggregation:
SELECT a.NAME, MAX(n.Type)
FROM ANIMAL a INNER JOIN
NEED n
ON a.SPECIES = n.A_SPECIES
GROUP BY a.Name
HAVING COUNT(*) = 1;
Or an alternative uses NOT EXISTS:
SELECT a.NAME, n.Type
FROM ANIMAL a INNER JOIN
NEED n
ON a.SPECIES = n.A_SPECIES
WHERE NOT EXISTS (SELECT 1
FROM need n2
WHERE n2.A_SPECIES = n.A_SPECIES AND
n2.Type <> n.Type
);
In practice, this probably has better performance, particularly with an index on need(a_species, type).

"!= nor <>" doesn't work when selecting data with subquery

i have table employee:
And what I want to select is list of employees who do not have a designated chief who works in the same department (employee #24 have chief from another department and some ppl doesn't have chief at all)
So here is the question:
Why this works:
SELECT
*
FROM
employee a
WHERE
a.cheif_id NOT IN (SELECT
cheif_id
FROM
employee b
WHERE
b.dep_id = a.dep_id
AND b.id = a.cheif_id);
but this does not:
SELECT
*
FROM
employee a
WHERE
a.cheif_id <> (SELECT
cheif_id
FROM
employee b
WHERE
b.dep_id = a.dep_id
AND b.id = a.cheif_id);
In addition if we want to select employees who Do have a designated chief who works in the same department '=' and 'in ()' works.
Sorry for cheif mistake.
if there are multiple data in your Subquery,you can't use <>,you can use NOT IN
I think you can use JOIN instead of subquery
SELECT e1.name chiefname,e2.*
FROM employee e1
INNER JOIN e2
ON e1.dep_id = e2.dep_id AND e1.id = e2.cheif_id

Is this sql query correct?

Using table below
http://i.imgur.com/rIMgFZC.png
How do i display the names of toys that processed by Female Employees who are in level 3, level 4, and level 5 (not level 1 or 2) and a list of all toys’ name with stores’ postcode 10005. Write using union.
SELECT Toy_name
FROM Toy T
INNER JOIN hire_transaction H on T.toy_id = H.toy_id
INNER JOIN Employee E on H.E_id = E.E_id
WHERE E_Sex = ‘F’
AND E_Level between ‘3’ and ‘5’
UNION
SELECT Toy_name, Store_id
FROM Toy T, Store S
WHERE T.Store_ID IN(
SELECT Store_ID
FROM STORE S
WHERE Store_Postcode = ‘10005’);
this is my attempt. am i correct?
SELECT Toy_name
FROM Toy T
INNER JOIN hire_transaction H on T.toy_id = H.toy_id
INNER JOIN Employee E on H.E_id = E.E_id
WHERE E_Sex = 'F'
AND E_Level between 3 and 5
UNION
SELECT Toy_name
FROM Toy T
WHERE T.Store_ID IN(
SELECT Store_ID
FROM STORE S
WHERE Store_Postcode = '10005');
When using unions the distinct selects must have the same number and types of columns.
Removed the unnecessary implicit join in your second query.
You used the wrong quotation marks, inserted the single quotes.

Get list of students with max number in each class

I want to get the list of students from db, who have get maximum number in each class with student name. Using MySQL DB.
I have the following tables like Student, classes, result (with different years results)
Tables structure student(student_id,student_name,class_id,address), class(class_id,class_name), results(result_id,student_id,year,marks)
and I need list like
Student Name class Marks
Jon A-1 800
Steve B-1 789
Edit corrected code, comment was correct
Try the code on this SQL Fiddle link
You could use a subquery to filter the students with the highest mark per class:
select s.student_name
, c.class_name
, r.marks
from results r
join student s
on r.student_id = s.student_id
join class c
on c.class_id = s.class_id
where r.result_id =
(
select r2.result_id
from student s2
join results r2
on s2.student_id = r2.student_id
where c.class_id = s2.class_id
order by
r2.marks desc
limit 1
)
Live example at SQL Fiddle.
select s1.student_name, c1.class_name, r1.marks
from student s1, class c1, results r1,
(select s2.class_id, max(r2.marks) marks
from results r2, student s2
where r2.student_id = s2.student_id
group by s2.class_id) agg
where r1.marks = agg.marks
and r1.student_id = s1.student_id
and s1.class_id = c1.class_id
and s1.class_id = agg.class_id