I currently have this query:
SELECT s.firstName, s.lastName, sum(correct) AS score
FROM student s
JOIN test t ON s.id = t.studentid
WHERE t.testType = 1 GROUP BY lastName, firstName
But I also want it to show
WHERE t.testType = 2
and testType 3 and 4 also.
I want to have it all in the same row. Is this possible?
You could use the in style to select from a multiple of different values
SELECT s.firstName, s.lastName, sum(correct) AS score
FROM student s
JOIN test t ON s.id = t.studentid
WHERE t.testType in ( 1,2,3,4 )
GROUP BY lastName, firstName
I think between clause can answer your question - http://www.tutorialspoint.com/mysql/mysql-between-clause.htm
where t.testType between 1 and 4
SELECT s.firstName, s.lastName, b.score, c.score2
FROM student s
JOIN (
SELECT s.id,s.firstName, s.lastName, sum(correct) AS score FROM student s JOIN test t ON s.id = t.studentid WHERE t.testType = 1 GROUP BY lastName, firstName
) b ON (s.id = b.id)
JOIN (
SELECT s.id,s.firstName, s.lastName, sum(correct) AS score2 FROM student s JOIN test t ON s.id = t.studentid WHERE t.testType = 2 GROUP BY lastName, firstName
) c ON (s.id = c.id)
GROUP BY lastName, firstName
I just used a bunch of JOIN statements. It works. Just doesn't show anything if either value is 0.
Related
My problem is to write a SQL query to return the names of all teachers who have taught a course where at least 2 students received a B- or better in the course.
My tables are:
Courses(id, name, teacher_id)
Grades(student_id, course_id, grade)
Students(id, name, email, password)
Teachers(id, name)
I used the following query:
SELECT * FROM grades JOIN teachers WHERE grades.grade = 'B-'
But shows all teacher like
You can use exists() for that to check if for each teacher exists a course that had more then 2 'b-' or better
So your query should be:
SELECT * FROM Teachers t
WHERE EXISTS(SELECT c.teacher_id from Courses c
inner join grades g ON c.id= g.course_id
where t.id = c.teacher_id and g.grade in('B-','B','A-','A','A+')
group by c.teacher_id having count(*) > 1)
This should work:
Select distinct Teachers.name from Courses join Teachers on Courses.teacher_id = Teachers.id where Courses.id in (Select course_id from (Select course_id, count(student_id) as 'total' from Grades where grade = 'B-' or grade = 'B' or grade = 'B+' or grade = 'A-' or grade = 'A' group by course_id) a where a.total > 1)
I have four tables like this:
schoolyear (id)
student (id, schoolyear_id)
test (id)
grade (id, test_id, student_id, score)
A student is associated with a schoolyear (through fk), and a grade is associated with a test and a student through fk's.
I want all students for a particular schoolyear to be returned regardless, and join the test score for the student along with all other fields from the student table if it exists. If not, the score field should be null. Here is what I have:
SELECT *, `student`.`id` as `studentid`
FROM `student`
LEFT JOIN `grade` ON `grade`.`student_id` = `student`.`id`
WHERE `student`.`schoolyear_id` = ?
There's nothing in my current statement telling it a particular test yet, but that's what I want.
SELECT *, `student`.`id` as `studentid`, t.*
FROM `student`
LEFT JOIN `grade` ON `grade`.`student_id` = `student`.`id`
LEFT JOIN `test` t ON `t`.`id` = `grade`.`test_id`
WHERE `student`.`schoolyear_id` = ?
and test_id = ?
Just add the conditional to the ON clause. This will ensure that students stay included, even if there's no grade for that test.
SELECT g.*, s.id
FROM Student s
LEFT JOIN Grade g
ON g.student_id = s.id
AND g.id = ?
WHERE s.schoolyear_id = ?
I have an issue on fetching some data. I have 4 tables
user
user_profile
user_income
tax_category
I need to select the tax category applicable to each user. For that i have two queries
The first one select the total income and age of the user and the second one to select the tax category applicable to the user. But i was not been able convert this to one query
SELECT userid,user_profile_gender,date_part('years',age(user_profile_dob))+1 AS userage,incomeresult.totalincome FROM user
LEFT JOIN user_profile ON user_profile_userid = user.userid
INNER JOIN
(SELECT SUM(income_amount) totalincome, income_userid FROM user_income
WHERE income_date BETWEEN '2012-03-30' AND '2014-03-30'
GROUP BY income_userid) AS incomeresult ON user.userid = incomeresult.income_userid
WHERE user.status = 1
SELECT * FROM tax_category
WHERE 70 BETWEEN taxcategory_agefrom AND taxcategory_ageto AND taxcategory_gender=1 AND 12000 BETWEEN taxcategory_incomefrom AND taxcategory_incometo
In the second query 70 should be the value from userage,1 from user_profile_gender and 12000 from incomeresult.totalincome.
Is it possible to create such a query? I am using PostgreSQL 8.4
I guess you could use CTE syntax:
WITH A AS
(
SELECT
userid,
user_profile_gender,
date_part('years',age(user_profile_dob))+1 AS userage,
incomeresult.totalincome
FROM
user
LEFT JOIN user_profile ON user_profile_userid = user.userid
INNER JOIN
(SELECT SUM(income_amount) totalincome, income_userid FROM user_income
WHERE income_date BETWEEN '2012-03-30' AND '2014-03-30'
GROUP BY income_userid) AS incomeresult ON user.userid = incomeresult.income_userid
WHERE
user.status = 1
)
SELECT *
FROM
tax_category
INNER JOIN A
WHERE A.userage BETWEEN taxcategory_agefrom AND taxcategory_ageto AND taxcategory_gender=1 AND A.totalincome BETWEEN taxcategory_incomefrom AND taxcategory_incometo
select
userid,
user_profile_gender,
date_part('years', age(user_profile_dob)) + 1 as userage,
incomeresult.totalincome,
tax_category.*
from
user
left join
user_profile on user_profile_userid = user.userid
inner join
(
select sum(income_amount) totalincome, income_userid
from user_income
where income_date between '2012-03-30' and '2014-03-30'
group by income_userid
) as incomeresult on user.userid = incomeresult.income_userid
left join
tax_category on
date_part('years', age(user_profile_dob)) + 1 between taxcategory_agefrom and taxcategory_ageto
and taxcategory_gender = 1
and totalincome between taxcategory_incomefrom and taxcategory_incometo
where user.status = 1
I am struggling with a MYSQL query - I have 2 tables :
Table 1 (info) containing UID, first_name, last_name.
Table 2 (card) containing UID, pic .
What I am trying to do is get all results into an array:
WHERE UID IN '$ids' AND LEFT(last_name,1) = '$letter' ORDER BY last_name, first_name ASC
I figured an INNER JOIN so my current code is:
("SELECT UID, first_name, last_name, pic FROM
(SELECT info.first_name,info.last_name,card.pic FROM info
INNER JOIN card ON info.UID=card.UID)
WHERE LEFT(last_name,1) = '$letter' ORDER BY last_name, first_name ASC")
This is producing the following error though:
'Every derived table must have it's own alias'.
Am I going about this the right way with inner join, and how do I give the derived table an alias? Thanks in advance!
select b.UID, g.first_name, g.last_name, b.pic
from user_data.general_info g
inner join user_data.Bcards b on g.UID = b.UID
where LEFT(g.last_name, 1) = '$letter'
order by g.last_name, g.first_name asc
The inner query should be named.
SELECT users.UID, users.first_name, users.last_name, users.pic FROM
(SELECT info.first_name,info.last_name,card.pic FROM user_data.general_info
INNER JOIN user_data.Bcards ON general_info.UID=Bcards.UID) users
WHERE LEFT(users.last_name,1) = '$letter' ORDER BY users.last_name, users.first_name ASC
I have a table containing persons information (one row per person) and another table containing persons photos filenames (many rows per person). I want to select a group of persons (based on another table) but only one photo per person.
My old SQL was like this:
SELECT persons.personID, persons.name, persons.photo_filename, movie_cast.role
FROM persons, movie_cast
WHERE persons.personID = movie_cast.personID
AND movie_cast.imdbID = ?
ORDER BY movie_cast.castORDER
LIMIT 9';
But here, the 'persons' table contains also a 'photo_filename' column. In my new database design, this column is in another table. So if I try to get the photo_filename from the new table I get all the photos available for each person, but I need to get only one.
How to do it?
In the first example I have assumed there is always a photo, and am just grabbing the highest sorted photo filename alphabetically as a means to get a consistent photo for each user each time you run the query.
SELECT p.personID, p.name, ph.photo_filename, mc.role
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID
INNER JOIN (
select personID, max(photo_filename) as MaxPhotoName
from photos
group by personID
) phm on p.personID = phm.personID
INNER JOIN photos ph on phm.personID = ph.personID
and phm.MaxPhotoName = ph.photo_filename
WHERE mc.imdbID = ?
ORDER BY mc.cast
LIMIT 9
If there is a photo_date column and you want to use the newest photo you can do it like this:
SELECT p.personID, p.name, ph.photo_filename, mc.role
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID
INNER JOIN (
select personID, max(photo_date) as MaxPhotoDate
from photos
group by personID
) phm on p.personID = phm.personID
INNER JOIN photos ph on phm.personID = ph.personID
and phm.MaxPhotoDate = ph.photo_date
WHERE mc.imdbID = ?
ORDER BY mc.cast
LIMIT 9
If there is not always a photo, you can use a LEFT OUTER JOIN so that you will still get all your records back:
SELECT p.personID, p.name, ph.photo_filename, mc.role
FROM persons p
INNER JOIN movie_cast mc ON p.personID = mc.personID
LEFT OUTER JOIN (
select personID, max(photo_date) as MaxPhotoDate
from photos
group by personID
) phm on p.personID = phm.personID
LEFT OUTER JOIN photos ph on phm.personID = ph.personID
and phm.MaxPhotoDate = ph.photo_date
WHERE mc.imdbID = ?
ORDER BY mc.cast
LIMIT 9