STUDENT table which is used to store the student info and COURSE table which is used to store the Course info. the relationship between STUDENT and COURSE is one to many.
"Not Equal" and "Not Contains" are not giving the correct results incase of one to many relationship.(if we make the direct left join with COURSE table)
sample query
SQL Fiddle
Table: STUDENT
id name
----------- ----------
1 a
2 b
3 c
Table: COURSE
id name student
----------- ---------- ----------
10 x 1
11 y 1
11 y 2
10 x 3
In the example, I would like to obtain all students who are not associated with the course 'y'. But, when I add join and then apply filter, if a student (here student 'a') is associated with 'y' and another subject, he is shown in result. But, I
should not have student 'a' in the result as he is associated with 'y'.
In the following query, I was only expecting a single result
SELECT * FROM stu
JOIN cour ON stu.id = cour.student
WHERE cour.name != 'y'
id name id name student
----------- ---------- ----------- ---------- ----------
1 a 10 x 1
3 c 10 x 3
And multiple logical operations are also possible in the criteria. could you please suggest a query to achieve this?
Related
I need to compare trainers, who have a number of qualifications, against courses, which have a number of
This feels like it should be easy but I just can't get my head round it. Simplified example:
[TrainerQuals]
TrainerID QID
----------------
1 1
2 2
3 1
3 2
[CourseRequiredQuals]
CourseID QID
----------------
1 1
2 2
3 1
3 2
For a given course ID, list trainers allowed to teach that course,
by making sure the trainer has every QID for the course
So, expected output for #courseid = 1
TrainerID
---------
1
3
Expected output for #courseid = 2
TrainerID
---------
2
3
Expected output for #courseid = 3
TrainerID
---------
3
I have tried various join types and conditions but they all give me results where any of the IDs match and no further differences to filter on.
EDIT: Added an SQL Fiddle:
http://sqlfiddle.com/#!18/c852e1/2
A join with aggregation can be used here:
SELECT tq.TrainerID
FROM TrainerQuals tq
LEFT JOIN CourseRequiredQuals crq
ON crq.QID = tq.QID
WHERE crq.CourseID = 1 -- or 2, or 3
GROUP BY tq.TrainerID
HAVING COUNT(*) = COUNT(crq.QID);
The assertion in the HAVING clause ensures that every trainer record has a matching course record.
I have oracle11 table like this:
id name have_child
----------- ---------- ------------
1 Alison N
2 Mary N
3 Meg Y
4 Mary N
5 Meg N
where have_child is probably Boolean = Y/N.
I want to do query to list wrong behavior where one name can be Y and N - like Meg:
id name have_child
----------- ---------- ------------
3 Meg Y
5 Meg N
As a result I want to list entire rows.
I do not want to list proper duplicates - like Mary:
id name have_child
----------- ---------- ------------
2 Mary N
4 Mary N
I know how to count particular names and list what names appears more than 1 time like this:
SELECT name from table
GROUP BY name
HAVING COUNT(*)>1;
This could be a way:
select id, name, have_child
from (
select t.*,
count(distinct have_child) over (partition by name) as num
from yourTable t
)
where num > 1
The inner query simply lists all the records of the table, adding a column which gives the number of different values of have_child for the same name.
The external one simply filters for rows in which this number is greater than 1.
I'm trying to join two tables together. 1 table is Users and their responses and the 2nd table is Answer ID that corresponds to different options that the User can select.
In Table 2, there are some user entered entries.
In table 1, any user entered value is Answer ID = 1. Other than the Answer ID =1, the response id and the answer id will match.
How do I join the two tables together?
I joined on the identifier but as there are multiple of each one, it creates duplicates.
Snippet 1:
Select *
from Table1
Join Table2 on Table1.identifier = Table2.identifier
Otherwise, Snippet 2:
select *
from Table1
Join Table2 on (Table1.identifier = Table2.identifier AND
table2.response_id = table1.answer_id)
This fails because Response_id is var and answer id is INT.
When I do an AND condition for the join, it fails because user entries like 91.6 and then the answer id = 1.
With this snippet I get nothing because
Conversion failed when converting the varchar value '91.6' to data type int.
For example, I want the table join to skip the matching when answer id = 1 (because answer_id=1=user entered) and match everything else.
Table 1
Identifier Answer_iD Text
-------------------------------------
1 2 Male
1 3 Female
2 1 User Entered
3 2 Answer1
3 3 Answer2
3 4 Answer3
Table2
User Identifier Response_id
---------------------------
Andy 1 2
Andy 2 91.6
Andy 3 2
I want this output:
User Identifier Response_id Answer_Id Text
--------------------------------------------
Andy 1 2 2 Male
Andy 2 91.6 1 User entered
Andy 3 2 2 Answer1
Right now with my SQL snippet 1 I get
User Identifier Response_id Answer_Id Text
--------------------------------------------
Andy 1 2 2 Male
Andy 1 2 3 Female
I don't have access to edit any of the tables and right I basically look up each identifier and answer_id in Table 1 manually to see what it stands for in the table. There's a 100 of identifiers for each person so it gets pretty tiring quick.
Any workarounds welcome.
The answer to your question is this. Don’t understand what you want, but...
Select user, t2.identifier, t2.response_id, isnull(t1.answerid,t3.answerid)
From table2 t2
Left join table1 t1 on t1.identifier=t2.identifer and t1.answerid=t2.responseid
Left join table1 t3 on t3.identifer= t2.identifier and t3.answerid=1
First thing, I'm very new to databases so this is probably a very simple question, but I didn't know how to google it or how to give it a good title. I'm using postgres from python, but the problem is to put together the right query.
The scenario is the following. I hava a table with columns: ID, Trial, Subject, Invalid. It comes from a behavioral experiment where many subjects perform a task that is composed of several trials. Their responses can be invalid for different reasons, and depending on the reason there is a different invalidation code (an integer). A valid response has code 0.
------------------------------
ID | SUBJECT | TRIAL | INVALID
------------------------------
1 Peter 1 0
2 Peter 2 0
3 Peter 3 1
4 Peter 4 3
5 Mary 1 3
6 Mary 2 2
7 Mary 3 0
8 Mary 4 2
I would like to do two things (which I'm not sure how to do in an elegant way).
a) For each subject, I would like to know how many responses are in total and how many are valid. Now I'm making a query for each subjects, with the condition, e.g., WHERE Subject='Peter', but I can imagine that there is a more elegant solution.
Sample answer:
Subject Valids Total
Peter 2 4
Mary 1 4
b) For each subjects, I would like to know how many responses were invalid for each of the invalidation codes. Ideally I would get a table like:
Subject Invalid Count
Peter 0 2
Peter 1 1
Peter 2 0
Peter 3 1
Mary 0 1
Mary 1 0
Mary 2 2
Mary 3 1
Query #1: You want one result row per subject, so you group by subject. Use COUNT to count all records for a subject and COUNT in combination with CASE to count conditionally (all valid ones).
select
subject,
count(*) as all_responses,
count(case when invalid = 0 then 1 end) as valid_responses
from mytable
group by subject;
Query #2: Here you want one result row per subject and code, so you group by these two. Then count with COUNT.
select
subject,
invalid,
count(*) as responses
from mytable
group by subject, invalid;
UPDATE: In your updated request you want query #2 to show all subject/code combinations even if they have a count of 0. In order to do this, you'd have to create the set of all valid combinations first and then outer join your response table:
select
s.subject,
c.code,
count(m.invalid) as responses
from subjects s
cross join codes c
left join mytable m on (m.subject = subjects.subject and m.invalid = codes.code)
group by s.subject, c.code;
If you don't have tables for subjects and code (which you should), you can get them from your responses table instead:
select
s.subject,
c.code,
count(m.invalid) as responses
from (select distinct subject from mytable) s
cross join (select distinct invalid as code from mytable) c
left join mytable m on (m.subject = subjects.subject and m.invalid = codes.code)
group by s.subject, c.code;
Firstly, thank you for your time taken out to read this and please excuse the title, I wasn't quite sure how to describe my problem.
I have two tables. One for SystemUsers and another for PrintingPermissions.
PrintingPermissions Table
ID ---- SystemUserID --- PrintGroupTypeID --- CanPrint
1 ----------- 22 ------------------------- 1 -------------------True
2 ----------- 22-------------------------- 2 -------------------True
3 ----------- 22 ------------------------- 3 -------------------False
4 ----------- 23 ------------------------- 1 -------------------True
.
.
SystemUsers Table
ID ----------- Name
22 ----------- Robert
23 ----------- John
24 ----------- Simon
25 ----------- Kate
I need a select query that will generate a list of all users and their and their PrintPermissions based on the PrintingPermissions.PrintGroupTypeID.
The thing to note is that if the User is NOT listed in the PrintPermissions table I would still like their object to be created but with a CanPrintValue of FALSE or NULL.
i.e. the output of the supplied table data above should be like the following when selecting WHERE PrintGroupTypeID = 1.
.
.
RESULT (WHERE PrintGroupTypeID = 1)
Name ----- SystemUserID ----- CanPrint
Robert --------- 22 -------------------- True
John ----------- 23 --------------------- True
Simon --------- 24 --------------------- False //-- NOT in permission table, default false created
Kate ----------- 25 --------------------- False //-- NOT in permission table, default false created
Again, thank you very much for your time and please do let me know if you don't fully understand what I'm trying to achieve.
Rob
SELECT DISTINCT su.Name, su.ID, ISNULL(pp.CanPrint, CAST 0 AS BIT) as CanPrint
FROM SystemUser su
LEFT JOIN Printing Permissions pp ON su.ID = pp.SystemUserID AND pp.PrintGroupTypeID = #TargetPrintGroupTypeID
If you want null instead of false, you can omit the ISNULL function and just select CanPrint directly. This will give you three state results (true, false, null), and will allow you to determine which users are disallowed (false) and which are not in the print group (null).
How about:
Select s.name as name,
s.id as SystemUserID,
isnull(p.canprint, 'false') as CanPrint
From systemusers s
Left outer Join printingpermissions p on s.id = p.systemuserid
Where p.printgrouptypeid = 1
Ok, I've just managed to work it out.
Here's the query:
SELECT SystemUsers.Name, ISNULL(PrintingPermissions.CanPrint, 'FALSE') AS CanPrint
FROM SystemUsers LEFT OUTER JOIN
PrintingPermissions ON SystemUsers.ID = PrintingPermissions.SystemUserID AND
PrintingPermissions.PrintingGroupTypeID = #ID