I'm studying for my Database System exam tomorrow, and I'm working on an SQL question. This question is the only one from the paper that doesn't have an answer, but here's the question:
We use the following schema:
Professor(name, office, dept, age) (age is key)
Course(cno, title, dept) (cno stands for course number and is a key, title is the name of the course and dept is name of department offering the course)
Enrollment(cno, semester, inst_name, enrollment) (the key for this is (cno, semester)
Question: Write the following sql query: Output a table containing the single row "yes" in it if the age difference between the oldest and the youngest professors teaching the Database Systems course between 2000 and 2009 is at most 5 years
I amn't sure my approach is right, since we don't exactly want to output something from the table. Note that I think enrollment corresponds to when the instructor started teaching the course (which isn't the usual definition AFAIK).
My approach is as follows:
WITH dbsProfs AS (
SELECT P.age
FROM Professor P, Enroll E, Course C
WHERE P.name = E.inst_name AND C.cno = E.cno AND C.title = "Database Systems"
AND E.enrollment BETWEEN 2000 and 2009
)
SELECT "Yes"
FROM dbsProfs
WHERE MAX(dbsProfs.age) - MIN(dbsProfs.age) <= 5
I'm fairly confident with my temporary table. I'm doing a join on all 3 tables and filtering out to include only the ones relevant to my query. It's the other half I'm unsure about.
Any insight on whether this is correct/how to correct this would be much appreciated. I amn't convinced WHERE MAX(dbsProfs.age) - MIN(dbsProfs.age) <= 5 is valid SQL
With aggregate function you shoud use having
SELECT "Yes"
FROM dbsProfs
HAVING MAX(dbsProfs.age) - MIN(dbsProfs.age) <= 5
WITH dbsProfs AS (
SELECT MIN(P.age) as min_age,MAX(P.age) as max_age
FROM Professor P, Enroll E, Course C
WHERE P.name = E.inst_name AND C.cno = E.cno AND C.title = "Database Systems"
AND E.enrollment BETWEEN 2000 and 2009
)
SELECT CASE WHEN min_age<max_age THEN "Yes" END
FROM dbsProfs
It's true, you can't put aggregate functions in your WHERE statement. This question will take a bit more work.
This is the approach I would take:
SELECT CASE WHEN A.MaxAge - A.MinAge <=5 THEN "Yes" END
FROM
(
SELECT Max(Professor.age) AS MaxAge, Min(Professor.age) AS MinAge
FROM Professor INNER JOIN Enroll ON Professor.name = Enroll.inst_name
INNER JOIN Course ON Enroll.cno = Course.cno
WHERE Course.title = "Database Systems" AND Enroll.enrollment BETWEEN 2000 AND 2009
) AS A
This assumes enrollment is indeed the year the course was instructed (as you also assumed). You can use an iif statement if you're fond of SQL Server instead of the SELECT CASE (the latter being more t-SQL standards friendly).
Related
I am attempting to creat a VIEW for my class. I was instructed to make my Access Compatible syntax ANSI 92. I have done that but I keep getting a message saying to:
"Enter parameter Value for 'JR'."
But it should just be showing any with the JR in the field value.
Any idea what I am doing wrong?
SELECT Student.IDno, LastName, FirstName, Class AS
Junior, Major, GPA
FROM Student, Person
WHERE Student.IDno = Person.IDno
AND Class = “JR”;
I also have to include columns from 2-3 different tables, change the titles of two of the columns, and show only the records that have class = "JR".
Any advice on where to start looking for this info would be great.
Thank you.
EDIT: Thank you for the help with that last one. Now I'm trying to change this to be able to pull from multiple tables and I can't seem to figure anything out. When I run this code, it tells me it can't find the table or query. If I run each section alone, it works just fine. I need to pull some info from 4 tables...
SELECT Student.IDno, Person.LastName, Person.FirstName, Student.Class, Student.Major, Student.GPA
FROM Student, Person
WHERE Student.IDno = Person.IDno
AND Class = 'JR';
UNION
SELECT Student.IDno, Enrollment.OfferNo, Enrollment.Grade
FROM Student, Enrollment
WHERE Student.IDno = Enrollment.IDno;
The double-quotes present in your SQL code are 'smart quotes' or Unicode character 0x201C, as opposed to the standard double-quote, which is Unicode/ASCII character 0x0022.
Hence changing the SQL to either:
SELECT Student.IDno, LastName, FirstName, Class AS Junior, Major, GPA
FROM Student, Person
WHERE Student.IDno = Person.IDno
AND Class = "JR";
or:
SELECT Student.IDno, LastName, FirstName, Class AS Junior, Major, GPA
FROM Student, Person
WHERE Student.IDno = Person.IDno
AND Class = 'JR';
Will solve this.
However, I would also strongly suggest using an INNER JOIN (i.e. ANSI-92 syntax) in place of a cartesian product with join criteria in the WHERE clause (ANSI-89 syntax):
SELECT Student.IDno, LastName, FirstName, Class AS Junior, Major, GPA
FROM Student INNER JOIN Person ON Student.IDno = Person.IDno
WHERE Class = 'JR';
It is also advisable to state the table qualifier for each field (e.g. Person.LastName or Student.LastName) so as to avoid the improper use of reserved words or ambiguity arising from identically named fields in multiple tables.
In the code you have added to your question, you are attempting to UNION two SELECT queries which output a different number of columns, and presumably, different data types - this is invalid.
I imagine that you are actually looking to do this:
select
student.idno,
person.lastname,
person.firstname,
student.class,
student.major,
student.gpa,
enrollment.offerno,
enrollment.grade
from
(
student inner join person
on student.idno = person.idno
)
inner join enrollment
on student.idno = enrollment.idno
where
student.class = 'JR'
Pretty new to MySQL here. I have the following query that isn't quite working the way I want: **SELECT round(sum(temp_pop.pop_total * demographics.coefficient)) as demand, pop_proj.pop_total from pop_proj, d.age, d.coefficient, d.educationalattainment from demographics d JOIN (SELECT year,sum(pop_total), age FROM pop_proj GROUP BY year, age) AS temp_pop WHERE d.age = CASE WHEN temp_pop.age < 18 then '00 to 17' WHEN temp_pop.age > 64 then '65 to 80+' ELSE '18 to 64' end;**
The sources are the subquery shown above in the syntax which I'm trying to join with a table called "demographics" with only three columns that shows education level (educational attainment), an age range (age) - shown in the case statement, and a coefficient, used in the calculation at the beginning of the query. The pop_proj table provides a year, age, and population total (pop_total column). I'm trying to use temp_pop as an alias for the subquery. I'm fairly sure the case is written out correctly. However, when I run the query, it tells me this: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'mysql> SELECT round(sum(temp_pop.pop_total * demographics.coefficient)) as deman' at line 1
I also want to group the results by year and education level, I just haven't added that in there yet.
Previously I had it written only slightly differently and it was telling me it didn't recognize the column name pop_total, but haven't gotten a result without an error yet. I may be totally off on how write this query, but hoping I'm getting close. I would appreciate some help! Thanks in advance!
It's difficult to understand what you're really after but this may get you a step closer.
The below makes the assumption that you're relating demographics to pop_total only on the contrived age range string in your CASE which is suspicious and may not be valid.
This doesn't attempt to group the results, but that should be straightforward once you can see a working detailed output that meets your needs.
SELECT d.age, d.coefficient, d.educationalattainment, temp_pop.pop_total
FROM demographics d JOIN (
SELECT `year`, age, sum(pop_total) as pop_total
FROM pop_proj
GROUP BY `year`, age
) temp_pop ON d.age =
CASE WHEN temp_pop.age < 18 THEN '00 to 17'
WHEN temp_pop.age > 64 THEN '65 to 80+'
ELSE '18 to 64' END
;
I'm trying to do an assignment for my course where one of the questions is to get the faculty name, date hired (in dd-mon-yyyy format) and that have the same title as Erit Jackson in the database, who's title is Assoc Prof. My code looks identical to the example provided by the instructor, but when I run this code, I get the error:
2014 - Commands out of sync; you can't run this command now
I don't know what I'm doing wrong thus far?
SELECT CONCAT('Dr.', ' ', LName) As 'Faculty Name', DateHired
FROM Faculty
WHERE Title = (
SELECT Title
FROM Faculty
WHERE Title = 'Assoc Prof');
This doesn't make a lot of sense as written. It can be simplified:
SELECT CONCAT('Dr.', ' ', f1.LName) As 'Faculty Name', f1.DateHired
FROM Faculty f1
INNER JOIN Faculty f2
ON f1.Title = f2.Title
WHERE f2.FName = 'Erit'
AND f2.LName = 'Jackson';
The way you are using the subquery is redundant. You're asking the database for the person that has the title(select & from), that matches(where title =) a table of titles with the title of 'Assoc Prof'(subquery).
Your professor wants your subquery to find the title of Erit Jackson, not to specifically find the title "Assoc Prof". Do you see the difference? You won't ever have the text "Assoc Prof" in your query at all.
I am currently working with this query
SELECT DISTINCT
se.src_aet AS "Ripped By",
CONVERT(varchar(32), s.created_time, 113) AS "Date/Time Sent",
p.pat_name AS "Patient Name",
p.pat_id AS "Patient ID",
s.accession_no AS "ACC #",
p.pat_birthdate AS "DOB",
s.mods_in_study AS "MOD",
CONVERT(varchar(32), s.study_datetime, 113) AS "Study Date",
s.study_desc AS "Study Desc",
s.study_custom1 AS "Inst Name"
FROM
dbo.patient AS p
INNER JOIN
dbo.study AS s ON s.patient_fk = p.pk
INNER JOIN
dbo.series AS se ON se.study_fk = s.pk
WHERE
accession_no like '%OUT%'
AND s.created_time >= CAST(getdate() as DATE)
AND s.created_time < CAST(DATEADD(day, 1, getdate()) as DATE)
ORDER BY
"Date/Time Sent" DESC
In the above example, it comes back with:
RIPPED BY DATE/TIME SENT PATIENT NAME PATIENT ID ACC# DOB
BC 18 Aug 2014 12:58:44:297 DOE^JOHN^^^ HOSP1234 OUT 19510101
I have taken the last few columns away (in the above example output) for simplicity sake here.
It is working correctly. It comes back with a list of studies that have the word 'OUT' in the accession_no column and that have been written to the DB 'today'.
What I am wanting to return are all of the unique values for 'pat_id' in the dbo.patient table for those found in the query. Some of those patients found the query above might already exist in the dbo.patient table if they have been to our site before, but they will have a different 'pat_id'.
What I want the output to look like is:
RIPPED BY DATE/TIME SENT PATIENT NAME PATIENT ID_OUT PATIENT ID_EXIST ACC# DOB STUDY DATE STUDY DESC INST NAME
the column 'PATIENT ID_OUT' is the patient ID that would be on the study that has the value of 'OUT' in the accession_no column and the column 'PATIENT ID_EXIST' is the existing patient ID, if it does exist. The value for 'PATIENT ID_EXIST' may be blank in some cases if the patient is new.
I was thinking I was needing to do a sub-query here, but maybe that is not the right thing to do in this case? Correct me if I am wrong.
EDIT: I have provided an example of the output. I am trying to figure out if the patient in the output has a different 'Patient ID' based on searching for the pat_name and pat_dob in the query results. If there is another or more than one patient ID in the pat_id column, then I would like them in the output.
I hope this is clear :)
I usually tackle tasks like this by treating the query as a table and joining to it.
SELECT p.*
FROM dbo.patient p
INNER JOIN (your big query) q
ON q.pat_id = p.pat_id
I'm struggling to find a query which will return members who aren't friends of a certain member. Here is the layout of my tables:
member_login:
MemberID, email, password
member_info:
memberID, first_name, last_name
member_friends:
friendID, req_member, req_date, app_member, app_date, date_deactivated
I tried to use NOT IN to run a query that would return the opposite of friends but nothing I try seems to be working. Here's what I thought would work:
SELECT Mi.First_Name, Mi.Last_Name
FROM Member_Info Mi
WHERE Mi.Memberid NOT IN(
SELECT Mi.Memberid, Mi.First_Name, Mi.Last_Name
FROM Member_Info Mi, Member_Login Ml, Member_Friends Mf
WHERE Mi.Memberid = Ml.Memberid
AND (Mi.Memberid = Mf.Req_Member
AND Mf.App_Member = 1
OR Mi.Memberid = Mf.App_Member
AND Mf.Req_Member =1)
AND Ml.Date_Deactivated <= 0
AND Mf.App_Date > 0
);
Any ideas?
#Thedirktastik, please check the correct use of IN clause. Here in the MSDN you can take a look.
In you WHERE clause you are using IN so the subquery returning the values should return only Mi.Memberid column values. And your query is returning several different columns. Should be something like:
....
WHERE Mi.Memberid NOT IN(
SELECT Mi.Memberid
FROM....
what if you try
SELECT Mi.First_Name, Mi.Last_Name
FROM Member_Info Mi
WHERE Mi.Memberid NOT IN(
SELECT Mi.Memberid
FROM Member_Info Mi, Member_Login Ml, Member_Friends
WHERE Mi.Memberid = Ml.Memberid
AND (Mi.Memberid = Mf.Req_Member
AND Mf.App_Member = 1
OR Mi.Memberid = Mf.App_Member
AND Mf.Req_Member =1)
AND Ml.Date_Deactivated <= 0
AND Mf.App_Date > 0
);
because you are returning three values in your NOT IN ( ... ) when it should be one
SELECT Mi.Memberid, Mi.First_Name, Mi.Last_Name
should be
SELECT Mi.Memberid
you might get another error about your FROM statement as you will need to join to tables together to compare values but your friend table does not have any matching values so this could be a problem (poor design)
EDIT: database designs
A lot of this comes down to experience really but there are a few good books which you can check out like Head First SQL and Relational Database Design Clearly Explained (The Morgan Kaufmann Series in Data Management Systems) (Paperback), these are great books to learn the basics and basic design, i recommend you check them out
This is a really bad design, and probably the reason for the down votes. I would look into making the member_friends table an intersect table (junction table). It will make your design, and therefore queries, much easier to use and understand.