SQL - JOIN add additional requirement in another table - mysql

I'm looking for some guidance on the following. I have two SQL tables A and B.
Table A Contains a list of languages
language_id
language
1
English
2
French
3
Spanish
I would like select all languages, and do a check on Table B to see if it exists for a user in table B. A user can select multiple languages, and many users could opt for any give language. The Query will be for a specific userid.
Table B
language_id
userid
1
1
2
1
2
2
3
2
I am not sure how to add the condition "WHERE userid = 1", I am hoping it will provide the following result.
$stmt = "SELECT A.language_id, A.language, COUNT(B.userid) FROM A INNER JOIN B.language_id = A.language_id ORDER BY A.language";
So for userid 1 it would produce the following.
language_id
language
COUNT()
1
English
1
2
French
1
3
Spanish
0
I am just trying to check if the user has selected each language or not. Thank you in advance.

you can use below query for this.
select A.language_id, A.language, COALESCE(B.counter, 0)counter
FROM tableA A
LEFT OUTER JOIN (
SELECT language_id, COUNT(1)counter FROM tableB where userid=1 group by language_id
)B ON A.language_id = B.language_id

Related

SQL JOIN - comments with reactions (2 tables)

I need to make one SQL command.
From table with comments i'll get comment id, then
with this ID I need to get count of reactions with the same comment ID and user's names.
So for example I have this 2 tables:
Comments:
ID
Comm_text
1
Example text
2
Another example
and Reactions:
ID
comm_id
usr
etc..
1
1
Peter
another
2
1
John
collon
3
1
Dog
cuz
4
2
Cat
why not
I need to get this:
ID
Comm_text
Reactions_Count
Users
1
Example text
3
Peter, John, Dog
2
Another example
1
Cat
I tried this:
SELECT k.id, k.comm, COUNT(r.id) as reactions, r.usr
FROM `comms` k
INNER JOIN `reactions` r ON r.id=k.id
It's just one row with one comment and count of all rows in reaction table.
Thanks.
Try this query that makes the same output:
select comments.id as ID , comments.Comm_text as Comm_text ,
(select count(id) from Reactions where comm_id = comments.id) as Reactions_Count ,
(select coalesce(GROUP_CONCAT(usr ORDER BY usr DESC) , '') from Reactions WHERE comm_id = comments.id) as Users
from comments group by comments.id
You should use group by to group the comments and have just one row then use query to count and gather the data, based on each row of the group.
The GROUP_CONCAT attach the output with , and the coalesce set the output to a given string if the output was empty.
Read more about:
GROUP BY
GROUP_CONCAT
COALESCE
subquery
According to the names that u set in the example, this will work. Just fix the table names for your database structure.
SELECT `Comments`.`ID`, `Comments`.`Comm_text`, count(`Reactions`.`comm_id`) as react, `Reactions`.`usr`
FROM `Comments`
INNER JOIN `Reactions`
ON `Comments`.`ID`=`Reactions`.`comm_id`
GROUP BY `Reactions`.`comm_id`

How to find all children from another table?

I have two tables
CATEGORY
id category parent_id
1 Electronic
2 Furniture
3 Phone 1
4 LCD 1
5 Watch 1
6 Desk 2
ORDER
id customer product category_id
1 John Smartphone 3
2 Marry Montior 4
3 King Wood-Desk 6
I want to find all of electronic result by child_id.
Like this..
SELECT product FROM order WHERE category_id = (category.id = 1)
RESULT
product
Smartphone
Monitor
Is there any expression like this in MySQL?
You can use a join for this. You also will need to encapsulate the order table name with backticks because order is reserved (alternatively you could rename that table to save yourself from encapsulating everytime).
SELECT product FROM `order` as o
join category as c
on o.category_id = c.id
WHERE c.parent_id = 1
The on tells the DB what to data to join on. The as creates an alias so the full table name doesn't need to be written out everytime. (The as also is optional, I find it easier to read, FROM `order` o would be the same)
An alternative approach could be using a sub-query:
SELECT product
FROM `order`
WHERE category_id in (SELECT id FROM CATEGORY where parent_id = 1)
You have to use INNER JOIN
SELECT order.product
FROM order
INNER JOIN category
ON order.category_id = category.id
WHERE category.parent_id = 1
The ON keyword shows what columns will be compare between these tables. When you make a JOIN you need to put the table name before the column name separated with "." because it is possible to exist a column with the same name in both tables.

How to JOIN SELECT from multiple tables, where the SELECTS is based on different conditions?

I have three tables. One with notes Notes, one with users Users, and one a relational table between users and notes NotesUsers.
Users
user_id first_name last_name
1 John Smith
2 Jane Doe
Notes
note_id note_name owner_id
1 Math 1
2 Science 1
3 English 2
NoteUsers
user_id note_id
1 1
2 1
2 2
2 3
Hopefully, from the select statement you can tell what I'm trying to do. I am trying to select the notes that user_id = 2 has access to but doesn't necessarily own, but also along with this I'm trying to get the first and last name of the owner.
SELECT Notes.notes_id, note_name
FROM Notes, NotesUsers
WHERE NotesUsers.note_id = Notes.note_id AND NotesUsers.user_id = 2
JOIN SELECT first_name, last_name FROM Users, Notes WHERE Notes.owner_id = Users.user_id
My problem is that because the WHERE clause for first_name, and last_name versus that for notes are different, I don't know how to query the data. I understand that this is not how a JOIN works and
I don't necessarily want to use a JOIN, but I'm not sure how to structure the statement, so I left it in there so that you can understand what I'm trying to do.
You can join Notes with NoteUsers to check for access and with Users to add the user's details to the result:
SELECT n.noted_id, n.note_name, u.first_name, u.last_name
FROM Notes n
JOIN NoteUsers nu ON n.noted_id = nu.note_id AND nu.user_id = 2
JOIN Users u ON n.owner_id = u.user_id
you need here to use a query inside the main query. MySQL will return first all the note_id that the user with user_id = 2 has access to from NoteUser, then well build the outer query to return the first_name and the last_name of the owner.
SELECT u.first_name, u.last_name, n.note_name, n.note_id
FROM Notes AS n
LEFT JOIN Users AS u ON u.user_id = n.owner_id
WHERE n.note_id IN
(SELECT nu.note_id FROM NoteUser WHERE nu.user_id = 2)

Adding Default Values on Joining Tables

I have the following tables:
Users
user_id course_id completion_rate
1 2 0.4
1 23 0.6
1 49 0.5
... ... ...
Courses
course_id title
1 Intro to Python
2 Intro to R
... ...
70 Intro to Flask
Each entry in the user table represents a course that the user took. However, it is rare that users have taken every course.
What I need is a result set with user_id, course_id, completion_rate. In the case that the user has taken the course, the existing completion_rate should be used, but if not then the completion_rate should be set to 0. That is, there would be 70 rows for each user_id, one for each course.
I don't have a lot of experience with SQL, and I'm not sure where to start. Would it be easier to do this in something like R?
Thank you.
You should first cross join the courses with distinct users. Then left join on this to get the desired result. If the user hasn't taken a course the completion_rate would be null and we use coalesce to default a 0.
select c.course_id,cu.user_id,coalesce(u.completion_rate,0) as completion_rate
from courses c
cross join (select distinct user_id from users) cu
left join users u on u.course_id=c.course_id and cu.user_id=u.user_id
Step1: Take the distinct client_id from client_data (abc) and do 1 on 1 merge with the course data (abc1) . 1 on 1 merge helps up write all the courses against each client_id
Step2: Merge the above dataset with the client info on client_id as well as course
create table ans as
select p.*,case when q.completion_rate is not null then q.completion_rate else 0
end as completion_rate
from
(
select a.client_id,b.course from
(select distinct client_id from abc) a
left join
abc1 b
on 1=1
) p
left join
abc q
on p.client_id = q.client_id and p.course = q.course
order by client_id,course;
Let me know in case of any queries.

Mysql subselect alternative

I have a query that I know can be done using a subselect, but due to large table sizes (100k+ rows per table) I would like to find an alternative using a join. This is not a homework question, but it's easier to share an example in such terms.
Suppose there are two tables:
Students
:id :name
1 Tom
2 Sally
3 Ben
Books
:id :student_id :book
1 1 Math 101
2 1 History
3 2 NULL
4 3 Math 101
I want to find all students who don't have a history book. Working subselect is:
select name from students where id not in (select student_id from books where book = 'History');
This returns Sally and Ben.
Thanks for your replies!
Is performance the problem? Or is this just some theoretical (homework?) question to avoid a subquery? If it's performance then this:
SELECT *
FROM studnets s
WHERE NOT EXISTS
(SELECT id FROM books WHERE student_id = s.id AND book = 'History')
will perform a lot better than the IN you're doing on MySQL (on some other databases, they will perform equivalently). This can also be rephrased as a join:
SELECT s.*
FROM studnets s
LEFT JOIN books b ON s.id = b.student_id AND b.book = 'History'
WHERE b.id IS NULL