SQL - Select all skills - sql

it's been a while since I used SQL so I'm asking sorry if it's too easy.
I have to select all the skills that a user has, so I have three tables.
User (id, name)
Skills (id, name)
User_skills (id_user, id_skill)
If the user1 has 2 skills; for example Hibernate (id 1) and Java (id 2)
and the user2 has 1 skill; Java (id 1)
Passing 1 and 2, I want to retrieve users that have both.
With the IN() function I get all the users that have at least one of the skills, but I want to filter them out!
Thanks to all in advance

If one skill can only be assigned exactly once to a user (i.e. (id_user, id_skill) is the PK for the user_skills table), then the following will do what you want:
SELECT id_user
FROM user_skills
WHERE id_skill IN (1,2)
GROUP BY id_user
HAVING count(*) = 2

Join to the association table user_skills twice, putting the skill ID in the on clause of each join:
select u.*
from user u
join user_skills us1 on us1.id_user = u.id and us1.id_skill = 1
join user_skills us2 on us2.id_user = u.id and us2.id_skill = 2
By using join (and not left join) this query requires the user have both skills

SELECT name FROM user as u
WHERE
EXISTS( SELECT 1 FROM User_skills WHERE id_user=u.id AND id_skill=1 )
AND EXISTS( SELECT 1 FROM User_skills WHERE id_user=u.id AND id_skill=2 )

Related

join table on condition

I have 3 tables user, student_data, teacher_data. A user can be either student or a teacher. If it is the teacher I want to join user and teacher_data. And if it is a student then I want to join user with student_data.
How I can do this join with the condition.
I'd combine the two data tables in a sub-query, and then join the users to that.
SELECT
*
FROM
usr u
LEFT JOIN
(
SELECT user_id, datum, xxx, NULL AS yyy FROM student_data
UNION ALL
SELECT user_id, datum, NULL, yyy FROM teacher_data
)
d
ON d.user_id = u.id
https://dbfiddle.uk/?rdbms=oracle_21&fiddle=9b801ea739d42fe50c00ef4e17eaf143
NOTES:
The columns selected from the two data tables must match
Any unmatched columns must either be skipped or filled with NULL
Please don't call a table user, it's a reserved keyword and Oracle won't allow it.
You can write it like this:
select u.user_id,
s.student_id,
t.teacher_id
from usr u
left join student_data s on u.user_id=s.student_id
left join teacher_data t on u.user_id=t.teacher_id
where s.student_id is not null or t.teacher_id is not null
order by u.user_id
For every user_id check if he is a student or teacher, if he is student get his student column values else null, if he is a teacher get his teacher column values else null.
maybe try a union - something like this
select user_id, user_other_stuff
from user, student_data
where user.user_id = student_data.user_id
UNION
select user_id, user_other_stuff
from user, teacher_data
where user.user_id = teacher_data.user_id

Join 2 tables on foreign key while using count() in SQL

So I have two tables: Please see the ER diagram here
I want to use SELECT to create one table with "name" from the USER table, "id" as the foreign key for the two tables, and the count of friend_id as the number of friends each user has.
Here is my code:
SELECT name, id, (SELECT count(friend_id) as number
FROM friend
GROUP BY user_id)
FROM user
ORDER BY number DESC
I'm wondering what's the problem with these lines. Thank you!
You can use a subquery to calculate the count.
SELECT name, id, COALESCE(f.Count, 0) AS friend_count
FROM user u
LEFT JOIN (
SELECT user_id, COUNT(DISTINCT friend_id) AS Count
FROM friend
GROUP BY user_id
) f ON f.user_id = u.id
ORDER BY friend_count DESC
I used a LEFT JOIN so that if a user doesn't have a row in friend, it will still return a row with a friend count of 0 (thanks to COALESCE). I also added a DISTINCT so that if the friend has duplicates the friend is counted only one, might not be necessary especially if you have a UNIQUE INDEX setup on columns user_id, friend_id
Just add where to find only one id and remove group by because you have only one id for one or more friends as your diagram says.
SELECT name, id, (SELECT count(friend_id) as number
FROM friend
WHERE user_id = user.id)
FROM user
ORDER BY number DESC
I think this will be correct for you puprose
CREATE TABLE #user(
id VARCHAR(22),
[name] VARCHAR(255),
)
CREATE TABLE #friend(
user_id VARCHAR(22),
friend_id VARCHAR(22)
)
SELECT name, id, (SELECT COALESCE(COUNT(friend_id), 0)
FROM #friend f
WHERE f.user_id = u.id
GROUP BY user_id) as number
FROM #user u
ORDER BY number DESC
--Same query with join:
SELECT u.[name], u.id, COALESCE(COUNT(f.friend_id),0) number
FROM #user u
LEFT JOIN #friend f ON f.user_id = u.id
GROUP BY u.[name], u.id
ORDER BY number

How can I run my SQL, to get the result such as "John Doe, plumbing"

I have table category, with id and cat_name
Example: 152, Plumbing
I have table user, with category_id and name
Example: 152, John Doe
When I do
SELECT name, category_id FROM user
As a result I will have something like
John Doe, 152
Question:
How can I run my SQL, to get the result such as
John Doe, plumbing
It is quite easy to get this, Please use below query for the same
SELECT User.Name, Category.cat_name FROM User
INNER JOIN Category ON Category.Id = User.category_id
Happy coding :-)
Try basic JOINS
SELECT C.cat_name, U.Name
FROM category C JOIN User U ON C.id = U.category_id
this will work:
select a.name,b.cat_name from user a, category b
where a.category_id=b.id
As you can understand you have two tables, and there is some 1 to 1 relationship between records of these tables(user & category).
So here we will use a simple join to connect this two table.
SELECT c.cat_name, u.name
FROM category as c, user as u
WHERE c.id = u.category_id
When I do category as c, this is called aliasing. This has two benefits. One is to keep our query short and sweet(no need to repeat category, just use c) and second is SQL query engine has 100% clarity of what we want to select.
Let's you also want to select id, then you should use c.id or u.category_id.
Check these alternate methods-
IF OBJECT_ID('Category') IS NOT NULL
DROP TABLE Category
IF OBJECT_ID('User') IS NOT NULL
DROP TABLE [User]
CREATE TABLE Category
(ID INT,Cat_name VARCHAR(20))
CREATE TABLE [User]
(Category_id INT,[Name] VARCHAR(20))
INSERT INTO Category(ID ,Cat_name)
VALUES (152,'Plumbing')
INSERT INTO [User](Category_id ,[Name])
VALUES (152,'John Doe')
--Method 1 (using CROSS APPLY)
SELECT U.[Name], C.Cat_name FROM [User] U CROSS APPLY Category C WHERE U.Category_id=C.ID
--Method 2 (using INNER JOIN)
SELECT U.[Name], C.Cat_name FROM [User] U INNER JOIN Category C ON U.Category_id=C.ID
--Method 3 (using WHERE and WITHOUT JOIN)
SELECT U.[Name], C.Cat_name FROM [User] U,Category C WHERE U.Category_id=C.ID

H2 making one select from 2

I got 3 tables, Users, courses and course realation tables. I want to get users who aren't on specific course. So I figure I need somehow merge 2 selects with right join. How could I make one select from 2 selects?
SELECT ID, NAME, LASTNAME, ROLE FROM COURSERELATION JOIN USERS ON
ID_USER = ID WHERE ID_COURSE = ?
RIGTH JOIN
SELECT ID, NAME, LASTNAME, ROLE from COURSERELATION JOIN USERS ON
ID_USER = ID WHERE ID_COURSE != ?
You need to extract users for which it doesn't exist a record of that user for the specific course. You can filter the rows using a NOT EXISTS clause over a subquery.
Please try below query:
SELECT u.ID,
u.NAME,
u.LASTNAME,
u.ROLE
FROM USERS u
WHERE NOT EXISTS (SELECT 1
FROM COURSERELATION s
WHERE s.id_user = u.id
AND s.id_course = 'YOUR_COURSE_ID_HERE' )

How to exclude some rows from a SELECT Statement when 2 keys match?

I have 3 tables in my system: Courses, Scores and Users. Scores is a table which has the test results for each course and each user. So I have the ScoreID, The CourseID the UserID and the Score itself.
I want to show in some page the list of courses that the user didn't finished yet. So I want it to show all the courses excluding those the user has records in the Scores table (meaning he already has finished it).
How do I exclude the rows from a SELECT statement when certain CourseID and UserID match at the same time?
Assuming that this is for just one user, Mark Bannister's answer can be simplified a little...
SELECT
*
FROM
Courses
WHERE
NOT EXISTS (SELECT * FROM Scores WHERE CourseID = Courses.CourseID AND UserID = #userID)
Try:
select *
from Courses c
cross join Users u
where not exists
(select null from Scores s where s.CourseID = c.CourseID and s.UserID = u.UserID)
select *
from Courses
where not exists
(
select null from Scores where Scores.CourseID = Courses.CourseID
and Scores.UserID = Courses.UserID
)
Assuming you are using SQL Server you can
CROSS APPLY the courses and users, creating every possible combinations of courses and users
use NOT EXISTS to filter out those records where a UserID exists.
SQL Statement
SELECT *
FROM Courses c
CROSS APPLY Users u
WHERE NOT EXISTS (
SELECT *
FROM Scores
WHERE UserID = u.UserID
AND ScoreID = c.ScoreID
)
In case you are using any other DBMS, following should work on most DBMS's
SELECT *
FROM Courses AS c
, Users AS u
WHERE NOT EXISTS (
SELECT *
FROM Scores
WHERE UserID = u.UserID
AND ScoreID = c.ScoreID
)