I have a table where user_id is related to the role a user has, so not necessarily 1:1 user to role, because he can have multiple roles.
I am looking to only select the users which have role_id = 2 and not any other role. Can you assist?
select user_id, role_id
from users u
join roles r on u.user_id=r.user_id
(simply adding where role_id=2 is incorrect).
Current output:
user_id role_id
1 2
1 other
1 3
2 2
3 0
Expected output:
user_id role_id
2 2
Here is one method using aggregation:
select user_id, 2
from roles r
group by user_id
having min(role_id) = 2 and min(role_id) = max(role_id);
If role_id might be NULL, you can adjust this to:
having min(role_id) = 2 and min(role_id) = max(role_id) and count(role_id) = count(*)
Try this, it works well with NULLs also:
SELECT user_id, 2 FROM (
SELECT user_id, COUNT(role_id)
FROM roles
GROUP BY user_id
HAVING MIN(role_id) = 2 AND MAX(role_id) = 2 AND COUNT(*) = COUNT(role_id)
) AS t;
It is huge, but it is the simplest way to do this in PostgreSQL I think.
Related
I need to do a query to list all the users that may interacted with each other on the same category with a note. Basically, everyone that made a note on a category that the specific user made a note on. How can be done?
Let's say the USER ID is 3, that left a note (note_10):
ID U CATEGORY NOTE
1 3 5 'note_10'
2 1 3 'note_11'
3 2 5 'note_12'
4 5 2 'note_13'
5 6 5 'note_14'
6 7 5 'note_15'
Expected results:
U
2
6
7
ID number 2, 6, and 7 has posted on the same category.
I think you want a self-join with some filtering:
select t.*
from t join
t tt
on tt.category = t.category and
tt.note = 'note_10';
Here is a db<>fiddle.
If you want to filter out the original user, you can use:
from t join
t tt
on tt.category = t.category and
tt.note = 'note_10' and
tt.id <> t.id;
I think you want exists:
select t.u
from mytable t
where
t.u <> 3
and exists (select 1 from mytable t1 where t1.u = 3 and t1.category= t.category)
This gives you all users that posted on any category user 3 posted on.
This might generate duplicates in a given user has several categories in common with user 3 - if you want to avoid that, you can use select distinct instead.
Another option is window functions:
select u
from (
select u, count(*) filter(where u = 3) over(partition by category) cnt
from mytable
) t
where u <> 3 and cnt > 0
Hi friends from Stack Overflow. I am trying to run a query in MS Access, i just want one record per ID randomly, but I am getting all.
I tried with distinct is not working, and I try with top, didn't work either.
this is my table below originaldata
ID HotelName Role Email
__________________________
1 bandb admin test1#email.com
1 bandb admin test2#email.com
1 bandb admin test3#email.com
1 bandb user myuser#email.com
2 myhtl admin myhotel#email.com
3 ben admin ben#test.com
3 ben user ben2#test.com
4 moon admin moon#moon.com
4 moon admin moon#moon2.com
I want to get the below results
ID HotelName Role Email
__________________________
1 bandb admin test1#email.com
2 myhtl admin myhotel#email.com
3 ben admin ben#test.com
4 moon admin moon#moon.com
SELECT *
FROM OriginalData
WHERE (((OriginalData.[Role])='admin') AND ((OriginalData.[ID]) In (Select Distinct [ID] from [OriginalData] where [Role] = 'Admin' )));
Thank you for your time and help
SELECT ID, min(HOTELNAME), min(ROLE), min(EMAIL)
from OriginalData
group by ID
Assuming you would be OK with displaying the "minimum" email address per each hotel group, then the following query should work:
SELECT od1.ID, od1.HotelName, od1.Role, od1.Email
FROM OriginalData od1
INNER JOIN
(
SELECT ID, Hotel, MIN(Email) AS min_email
FROM OriginalData
WHERE Role = 'admin'
GROUP BY ID, Hotel
) od2
ON od1.ID = od2.ID AND
od1.Hotel = od2.Hotel AND
od1.Email = od2.min_email
WHERE
od1.Role = 'admin'
ORDER BY
od1.ID;
Edit:
Coincidentally, for the exact data you showed us, you might also be able to simplify to:
SELECT ID, Hotel, Role, MIN(Email) AS Email
FROM OriginalData
WHERE Role = 'admin'
GROUP BY ID, Hotel, Role;
However, this only works because all the columns you want to appear are either aggregates or constants. If you had other columns specific to a matching minimum row, this would not work.
Well this is easy but with a twist (notice the the TOP 1...it will return just one record
SELECT TOP 1 *
FROM OriginalData
WHERE OriginalData.[Role])='admin'
The problem is that in order to get Random you need to use something for randomize it for some value ...here lets take ID
So the SQL will be :
SELECT TOP 1 *
FROM OriginalData
WHERE OriginalData.[Role])='admin' AND ID = Clng(Rnd() * Dmax("ID","OriginalData")
I have a table with Users Sessions.
Columns - UserID, SessionID, Completed (bit).
I want to get the list of Users who has both Completed = 0 and Completed = 1
The query below will return the UserId has both the 0 and 1 of the Completed column entries.
SELECT UserId
FROM Users
WHERE Completed IN (0, 1)
GROUP BY UserId
HAVING COUNT(DISTINCT Completed ) = 2
I would do:
select userid
from suers
group by users
having min(completed) = 0 and max(completed) = 1;
Select distinct userid from sessions where completed=1
Intersect
Select distinct userid from sessions where completed=0
The intersect gets only users in both sets
I have two tables:
users: id, name;
friends: id, user_id, user_friend_id, approved;
I need to get all users where approved=0 for user_id = 3 or user_friend_is = 3 .
Try this
DB::table('users')->join('friends','users.id','=','friends.user_id')
->where('users.approved',0)
->where(function($query){
$query->orWhere('users.user_id',3)
->orWhere('users.user_friend_is',3)
})->select('users.*')->get();
It will select all users where approved=0 and (user_id = 3 or user_friend_is = 3)
Hope this will help.
I have got table "Members" with fields ID,UserID,GroupID
And I would like to select only GroupIDs where count of Members is more than 1 for each members, like this:
ID UserID GroupID
1 1 1 /* we are selecting groups for guy with ID 1, here are 3 people */
2 2 1
3 3 1
4 1 2 /* here the guy is alone in group, ignore him! */
5 1 3 /* select this one too for guy 1, because #members>1 */
6 2 3
Performing group select for guy with ID 1 including that there must be atleast 2 people in same group, so this would return: 1, 3
But I have no idea how to do this in SQL, I would like to do something like this, but, it obviously doesn't work:
SELECT GroupID
FROM Members
WHERE UserID=1
AND COUNT(
SELECT UserID FROM Members WHERE GroupID=**currently iterated group**
)>1;
Is it somehow possible?
If I understand correctly, you want groups with at least two members, one of which has userid = 1. The following query finds these groups using group by and having:
select m.groupId
from Members m
group by m.groupId
having count(*) > 1 and
sum(case when m.userid = 1 then 1 else 0 end) > 0;
This will return the groups with more than one member that user 1 is a member of:
select groupid
from members
where groupid in (select groupid from members where userid = 1)
group by groupid having count(*) > 1;
The solution offered by #GordonLinoff is probably better (more efficient) though.