Join SQL Table where join on column has user submitted entries - sql

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

Related

Return all rows where all rows of a child table match all rows of lookup

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.

How both asterisked lines are correct given the SQL statement

A new social network site has the following data tables:
Table users:
id
name
sex
1
Ann
null
2
Steve
m
3
Mary
f
4
Brenda
f
Table friends:
user1
user2
1
2
1
3
2
3
Select data that will be returned by the following SQL query:
SELECT users.name,
COUNT(*) as count
FROM users LEFT JOIN
friends ON users.id = friends.user1 OR users.id = friends.user2
WHERE users.sex = 'f'
GROUP BY users.id,
users.name;
Output:
name
count
Ann
1
Ann
2
Steve
1
Steve
2
Mary
1
Mary
2 **
Brenda
0
Brenda
1 **
The asterisked sections are the correct answers, but I don't quite understand why (Brenda, 1) would be an answer here when (Mary, 2) is also a correct answer.
This is a trap question. The query looks like your are selecting all female users (sex = 'f') and count their friendships. For this a left outer join on the friends table is applied, so we keep all female users, no matter whether they have friendships or not.
But then the query uses COUNT(*), which counts the joined rows. That is 2 for Mary and 1 for Brenda. If we wanted to count friendships, we'd have to count a column of the friends table, e.g. COUNT(friends.user1). Thus the outer joined rows having these columns set to null would be omitted from the count, and we'd get 2 for Mary and 0 for Brenda.

Sql query with selected and splited column value from another table

I have 2 tables
First table
Id Type Value
1 2 1,2,3,5
2 1 1,3,6
3 1 2,3,1,6
Second table
Id Name
1 Leon
2 Anna
3 Biorn
4 Alex
5 Peter
6 Luis
Values in First table are Ids in Second table.
I need query that returns all names by type from the first table
For example:
Type = 1
return: Leon,Anna,Biorn,Luis
type = 2
return: Leon,Anna,Biorn,Peter
I'm trying to create a View that will look like this:
Type Name
1 Leon
1 Anna
1 Biorn
1 Luis
2 Leon
2 Anna
2 Biorn
2 Peter
So I can easily select all the names by type, but I can't figure out how to do it. Please help!
You seem to recognize that this is a poor data structure. You should have a junction table -- storing lists of integers as a delimited string is not a SQLish data structure.
Sometimes, we are stuck with other people's bad design decisions. Here is one thing you can do:
select t1.type, t2.name
from table1 t1 join
table2 t2
on ',' + t1.value + ',' like ',%' + cast(t2.id as varchar(255)) + '%,';

How to count entries in sql "like in a loop"

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;

How to get all the records from the Table A and only common records from table B in sql

I have two tables Table A and Table B as follows.
TableA:
Id name
1 abc
2 john
3 jack
4 jill
Table B:
Id city phn
1 london 9876345
5 bangalore 2345678
3 chennai 5637473
I want records which are present in tableA but not in Table B.But the result should be
TableA:
Id name
1 abc
2 john
3 jack
4 jill
i.e even though 1 and 3 ids are present in Table B but they are still in table A.I want those records too.
5 bangalore 2345678
this records is not present in Table A.so i should not take this.
Really -- this simple? Don't think you need any joins then...
SELECT * FROM TableA
Good luck.
You need a left outer join.
Look into it here: http://en.wikipedia.org/wiki/Join_(SQL) and here: http://www.w3schools.com/sql/sql_join_left.asp
EDIT:
Your question makes no sense to be honest. In the heading you mention: "All the values in A and only common values in B" and then, you go on to state in the explanation that you need values from 'A' only and not B.. for that
select * from TableA will do.