I have four tables
users
ID display_name
1 Name1
2 Name2
3 Name3
A user can add books to table books
books
book_id AddedByuserID
1 1
2 1
3 2
4 3
Also a user can add ebooks to table ebooks
ebooks
ebook_id AddedByuserID
1 1
2 2
3 2
4 3
Now a user can add books only to his collection (not ebooks)
collection
userID book_id
1 1
1 2
1 3
I need an output like this:
display_name books_added ebooks_added books_in_collection
Name1 2 1 3
Name2 1 2 2
Name3 1 1 1
This is what got:
SELECT users.*, COUNT(DISTINCT collection.book_id) AS books_in_collection, COUNT(DISTINCT books.AddedByuserID) AS books_added, COUNT(DISTINCT ebooks.AddedByuserID) AS ebooks_added
FROM users LEFT JOIN collection ON users.ID = collection.userID
LEFT JOIN books ON users.ID = books.AddedByuserID
LEFT JOIN ebooks ON users.ID = ebooks.AddedByuserID
GROUP BY users.ID
ORDER BY display_name ASC
The user display_name gets displayed correct and also the collection count, but the two other counts are showing 1.
If I remove DISTINCT the collection count says 86, and the two other counts show nothing.
I try to understand LEFT join and read tutorials but i'm stuck at the moment.
I would suggest correlated subqueries:
select u.*,
(select count(*) from collection c where u.id = c.userId) as books_in_collection,
(select count(*) from books b where u.id = b.AddedByUserId) as books_added,
(select count(*) from ebooks e where u.id = e.AddedByUserId) as ebooks_added
from users u;
I don't know why you are filtering out the third user, however.
Related
I have 2 tables, this is my fiddle http://sqlfiddle.com/#!9/da5e4e/3
so basically i have 2 tables called personal and interview_score with personal.id = interview_score.personal_id.
assume this is my personal table
id name
1 John Doe
2 Nian
3 Rijali
and this is my interview_score table
id personal_id aspect_id
1 1 1
2 1 2
3 1 3
4 2 1
5 2 2
on this case, i just want to count how many personal_id in my interview_score table with this query
SELECT COUNT(i.id) as interviewed FROM personal p LEFT JOIN interview_score i ON i.personal_id = p.id GROUP BY i.personal_id;
but it returns just like this
interviewed
0
3
2
meanwhile, my expected result is just like this
interviewed
2
because on that table there are 2 personal_id based on that condition.
where my wrong at?
You can use join instead of left join also you need to group by p.id
SELECT COUNT(i.id) as interviewed FROM personal p JOIN interview_score i ON i.personal_id = p.id GROUP BY p.id;
from the above query you can get the count
To get count for a particular person
SELECT COUNT(i.id) as interviewed FROM personal p JOIN interview_score i ON i.personal_id = p.id and p.id=1 GROUP BY p.id;
I cant figure out one sql query. I need to get data from table, that are not paired in another table. So my limited knowlage is not enought here.
Lets say we have 3 tables client - category - client_category
TABLE CLIENT
id
name
1
client 1
2
client 2
TABLE category
id
name
1
category 1
2
category 2
3
category 3
TABLE client_category
id
id_client
id_category
1
1
1
2
2
1
3
2
2
3
2
3
DESIRED OUTPUT
client
category
client 1
category 2
client 1
category 3
This also need to work with more clients and categories.
SELECT client.name, category.name
FROM client
CROSS JOIN category
WHERE NOT EXISTS ( SELECT NULL
FROM client_category
WHERE client.id = client_category.id_client
AND category.id = client_category.id_category )
or
SELECT client.name, category.name
FROM client
CROSS JOIN category
LEFT JOIN client_category ON client.id = client_category.id_client
AND category.id = client_category.id_category
WHERE client_category.id IS NULL
You are interested in all possible links between client and category, that do not exist in client_category
SELECT
c.name, y.name
FROM client c
CROSS JOIN category y
LEFT JOIN client_category cc ON cc.id_client = c.id AND cc.id_category = y.id
WHERE cc.id IS NULL
ORDER BY c.id, y.id
output:
name
name
client 1
catgory 2
client 1
category 3
DBFIDDLE
I have table users:
id name
----- -----
1 Mark
2 John
3 Paul
4 Dave
5 Chris
and table matches:
id sender receiver matched
-- ------ -------- -------
1 2 5 2
2 1 3 0
3 1 2 0
So John have sent 1 request for match and his match is accepted.
Also John have receive 1 match which is still not accepted.
I'm using this code to find the names of the users by their ids
SELECT matches.sender as sender,matches.receiver as receiver,users.name as `userName`,
users.user as `userName2` FROM `matches`
INNER JOIN `users` ON matches.sender = users.id
WHERE '$id' IN (sender,receiver) AND matched='2'
but it's pulling out only sender's userName . When I type
...ON matches.sender = users.id AND matches.receiver = users.id ....
the result is 0
So I need to pull out the names of the 2 people.
I think you want two joins:
select m.*, us.name as sender_name, ur.name as receiver_name
from matches m join
users us
on m.sender = us.id join
users ur
on m.receiver = ur.id
where 2 in (m.sender, m.receiver) and
m.matched = 2;
I need help on how to set up an QUERY that will result in different outputs based on the results that it achieves on the way and I'm completely stuck!
I'll give you some more details, first of all, here's my current database setup:
#USERS
id username etc..
1 alex123
2 bonnie9
3 clyde_x
#COURSES
id course_name visibility etc..
1 Name 1 1
2 Name 2 0
3 Name 3 1
#COURSE_ENROLMENT
id user_id course_id
1 1 1
2 1 2
3 3 1
The scenario is as following..
I need to list the courses to the users that are enrolled to it, which is quite easily done by something like:
SELECT
*
FROM COURSES C
JOIN COURSE_ENROLMENT E ON C.ID = E.COURSE_ID
However. If the course visibility (Database: Course, Column: visibility) is set to be visible for everyone = 1, then it will override or just ignore the enrolment and show the course to all users anyway.
How can I achieve something like this? I've tried to research CASE but can't really figure out how to proceed. Greatest thanks for any help!
To answer this you're going to need to LEFT JOIN your COURSE and COURSE_ENROLLMENT tables using an OR, so either the person is enrolled in the subject OR the visibility is set to 0.
If you change your JOIN to a LEFT JOIN, that will give you all courses, regardless of whether someone has enrolled in them or not. You can then filter out the courses which have not had anyone enrolled and are not visible by checking for visibility = 1:
SELECT *
FROM Courses C
LEFT JOIN Course_Enrolment E ON C.id = E.course_id
WHERE C.visibility = 1 OR E.id IS NOT NULL
Output:
id course_name visibility id user_id course_id
1 Name 1 1 1 1 1
2 Name 2 0 2 1 2
1 Name 1 1 3 3 1
3 Name 3 1 null null null
Demo on dbfiddle
If visibility=1 means that the course will be returned for all users, then you can do it with a cross join for that case and UNION ALL:
select c.course_name, u.username
from users u
inner join course_enrolment e on e.user_id = u.id
inner join (
select * from courses where visibility = 0
) c on c.id = e.course_id
union all
select c.course_name, u.username
from users u
cross join (
select * from courses where visibility = 1
) c
order by course_name, username
I've got three tables:
staff
id name
1 Alex
2 John
3 Peter
staff_roles
id role_name
1 Barber
2 Driver
assigned_roles
id staff_id role_id
1 1 1
2 1 2
3 2 1
4 3 2
I want to get output smth. like:
name roles
Alex [{'id':'1','role_name':'Barber'},{'id':'2','role_name':'Driver'}]
John [{'id':'1','role_name':'Barber'}]
Peter [{'id':'2','role_name':'Driver'}]
I'm doing:
SELECT
staff.name,
GROUP_CONCAT(DISTINCT assigned_roles.role_id) as roles
FROM staff
LEFT JOIN assigned_roles
ON assigned_roles.staff_id = staff.id
LEFT JOIN roles
ON roles.id = assigned_roles.role_id
GROUP BY
staff.id
But how can I add role name to GROUP_CONCAT to have the output I want?
You can construct the final result like this:
SELECT s.name,
CONCAT('[',
GROUP_CONCAT(DISTINCT '{''id'':''', ar.role_id, ''',''role_name'':''', r.role_name, '''}'),
']')
FROM staff s LEFT JOIN
assigned_roles ar
ON ar.staff_id = s.id LEFT JOIN
roles r
ON r.id = ar.role_id
GROUP BY s.id;
There might be a typo with all those single quotes and unusual characters.