JPA Named Query Search within a List - sql

I have a group with a one to many relationship with users. (A group can have zero or 1+ users)
I was to write a jpa query that returns a groups if it has not users attached or if it does have users the id matches my id.
For example if I have group 1 contain user 1 and user 2. group 2 containing no users.
If I was user 3 I want to return group 2 only.
If I was user 2 then I want to return group 1 and group 2
Can I do this in JPA? I know about the IS EMPTY part of JPQL so I can get group 2 returned regardless of user. My problem is how to query inside the list.
Any pointers would be good.
Thank for any help

I think I have it. The answer is to left join with the list.
For example
SELECT g FROM Groups g left join fetch g.users u where (g.users IS EMPTY OR (u.id = :id))
Groups is my entity which contains a list of users

Related

group_concat multiple rows where given condition

I have 3 tables (User, User_usergroups , usergroup). I would like to get a list of user who has usergroup equal to "member" and other groups (group_concat) belonging to this user. How do I do that?
I got the first part of the query, but I could not get other groups, aggregated groups of this user (I like to use group_concat to concatenate other groups in one field.
SELECT user.userId, (group_concat(group_.name)???)
FROM User_ user join Users_UserGroups userGroups
on user.userId= userGroups.userId
join UserGroup group_ on userGroups.userGroupId = group_.userGroupId
WHERE group_.name="member";
Assume that is the 3 tables
The outcome will be
Many thanks for your great help.
It looks like my query is so complex and it has down vote from the administrator or someone. I wish whoever did this could add their comment to my query so that, in the future, I will know what I need to do to clarify my question to the community or make my question better. Here is the answer to my question.
First retrieve the list of userId.
Then join this "member" table with other tables to find the result from the list of retrieved ID (step 1).
As we aggregate the name of the groups, we need to use groupby.
Keywords to resolve this problem is to use an alias for subquery or nested SQL
select member.userid, member.screenName, group_concat(member.name)
from (SELECT User_.userid userid, User_.screenName screenName , UserGroup.name name
FROM UserGroup
JOIN Users_UserGroups
ON UserGroup.userGroupId = Users_UserGroups.usergroupid
JOIN User_
on Users_UserGroups.userId = User_.userId
WHERE UserGroup.name = "member")member
JOIN Users_UserGroups
ON member.userid = Users_UserGroups.userId
JOIN UserGroup
on UserGroup.userGroupId=Users_UserGroups.userGroupId
GROUP BY member.userid;

SQL query to exclude records that are part of a group

I can't believe this hasn't been answered elsewhere, but I don't seem to know the right words to convey what I'm trying to do. I'm using Ruby/Rails and PostgreSQL.
I have a bunch of Users in the DB that I'm trying to add to a Group based on a name search. I need to return Users that do not belong to a particular Group, but there is a join table as well (UserGroups, with the appropriate FKs).
Is there a simple way to use this configuration to perform this query without having to result to grabbing all the Users from which belong to the group and doing something like .where.not(id: users_in_group.pluck(:id)) (these groups can be pretty huge, so I don't want to send that query to the DB on a text search as the user types).
I need to return Users that do not belong to a particular Group
SELECT *
FROM users u
WHERE username ~ 'some pattern' -- ?
AND NOT EXISTS (
SELECT FROM user_groups ug
WHERE ug.group_id = 123 -- your group_id to exclude here
AND ug.user_id = u.id
);
See:
Select rows which are not present in other table

Get all data of users after grouping by

I have two tables "Users" "Bookings" and I merged two tables and groping by the booking and users count and get a new table which has the count of users who made a specific count of bookings ex:
so in the first column (62 users made 3 booking and the second columns 52 users made 4 bookings)
I want to get the data of users when I click on any line on the graph, means when I click on the first line on the graph I want to show the 62 users in a table, can I do this or not?
If you want a SQL solution, it would use group by and having:
select userid
from bookings
group by userid
having count(*) = 3;
This gives the list of user ids. You can use in, exists, or join to get additional information about the users if that is what you really want.

SQL - I need to see how many users are associated with a specific set of ids

I'm trying to identify a list of users that all have the same set of IDs from another table.
I have users 1, 2, 3, and 4, all that can have multiple IDs from the list A, B, C, and D. I need to see how many users from list one have ONLY 3 IDs, and those three IDs must match (so how many users from list one have ONLY A, B, and C, but not D).
I can identify which users have which IDs, but I can't quite get how to get how many users specifically have a specific set of them
Here is the SQL that I'm using where the counts just aren't looking correct. I've identified that there are about 7k users with exactly 16 IDs (of any type), but when I try to use this sql to get a count of a specific set of 16, the count I get is 15k.
select
count(user_id)
from
(
SELECT
user_id
FROM user_id_type
where user_id_type not in ('1','2','3','4','5')
GROUP BY user_id
HAVING COUNT(user_id_type)='16'
)
So you want users with 3 IDs as long as one of the IDs is not D. How about;
select user
from table
group by user
having count(*) = 3 and max(ID) <> 'D'
The HAVING clause is useful in situations like this. This approach will work as long as the excluded ID is the max (or an easy change for min).
Following your comment, if the min/max(ID) approach isn't viable then you could use NOT IN;
select user
from table
where user not in (select user from table where ID = 'D')
group by user
having count(*) = 3
Following the updated question, if I've understood the mapping between the initial example and reality correctly then the query should be something like this;
SELECT user_id
FROM user_id_type
WHERE user_id not in (select user_id from user_id_type where user_id_type in ('1','2','3','4','5'))
GROUP BY user_id
HAVING COUNT(user_id_type)='16'
What is odd is that you appear to have both a table and a column in the table with the same name 'user_id_type'. This isn't the clearest of designs.

SQL Stored procedure

I have 3 tables:
tbl_Image from which a list of all images will be obtained
A user table from which User ID will be obtained
and an association table of Image and Member called tbl_MemberAssociation.
My work flow is that a user can upload image and this will be stored in to image table. Then all users can view this image and select one of three choice provided along with the image. If user selects an option it will be added to Association table. No user can watch same image more than once. So multiple entries will not be there.
Now I want to find the % of match by getting the list of members choose the same option and different option corresponding to all common images for which they have provided their option.
I.e. say if 3 users say A, B and C view an image of tajmahal. If A and B opted beautiful as choice and C as "Not Good ". For another image say Indian Flag A B and C opted same as Salute. Then for User A: B have 100 % match (since they selected same option both times). For A : C have 50% match one among 2 same.
So this is my scenario, in which I have to find all matched corresponding to currently logged in User.
Please help me.... I am totally disturbed with this procedure.
I have made some assumptions about the actual structure of your tables, but if I understand what you are looking for then I think this query will get the results you are wanting. You may have to make a few modifications to match your table structures.
SELECT
matches.UserName,
CAST(matches.SameRatings AS FLOAT) / CAST(ratings.UserRatingCount AS FLOAT) AS MatchPercent
FROM
tbl_User
CROSS APPLY
(
SELECT
COUNT(*) UserRatingCount
FROM
tbl_MemberAssociation
WHERE
UserId = tbl_User.UserId
) ratings
CROSS APPLY
(
SELECT
u1.UserId,
u1.UserName,
COUNT(*) AS SameRatings
FROM
tbl_MemberAssociation ma
INNER JOIN
tbl_MemberAssociation ma1
ON
ma.ImageId = ma1.ImageId
AND ma.Rating = ma1.Rating
AND ma.UserId <> ma1.UserId
INNER JOIN
tbl_User u1
ON
ma1.userId = u1.UserId
WHERE
ma.UserId = tbl_User.UserId
GROUP BY
u1.UserId,
u1.UserName
) matches
WHERE
tbl_User.UserId = #UserId
ORDER BY
MatchPercent DESC
#UserId could be passed as an input to the stored procedure.
The 1st CROSS APPLY "ratings" is getting a count of for the total number of ratings for the logged in user.
The 2nd CROSS APPLY "matches" is getting a count of the number of like ratings for the other users in the database.
The result set uses the counts calculated by the two CROSS APPLY queries to compute the match percentage between the logged in user and the other users who have rated the same images as the logged in user.