Compare bitmasks in the H2 database - sql

Is there a way to compare bitmasks in the h2 database, similar to what has been asked in Comparing two bitmasks in SQL to see if any of the bits match ?
Having a table of users with different roles, I'd like to select all users that are programmers.
User Table
----------
ID Username Roles
1 Dave 6
2 Charlie 2
3 Susan 4
4 Nick 1
Roles Table
-----------
ID Role
1 Admin
2 Programmer
4 Designer
The select should be something like
SELECT * FROM UserTable WHERE Roles & 2 != 0
I know there is a BIT_AND function in h2 but do not know how to use it.

I was confused by the BITAND and BIT_AND functions. The select statement should look like
SELECT * FROM UserTable WHERE BITAND(Roles, 2) != 0

Related

Rails / ActiveRecord / SQL Return only 1 entry per user_id based on the highest priority

I have slightly complex relation going on my Rails application that I'm having a lot of trouble with.
For starters, there's a table that contains a list of roles which have an id and a priority. An example table looks like this
id priority
1 5
2 4
5 3
6 2
7 1
Now there's also a join_table that likes user ids with role ids in order to keep track of which user is assigned which role. The complicated part is that a user can have many roles
user_id role_id
3 1
3 2
3 7
4 1
4 5
4 6
What I'm trying to get is to filter done the users_roles table to only 1 entry per user based on the role with the lowest priority.
So what I'm trying to end up with is:
user_id role_id
3 7
4 6
The reason I would end up with this is due to the fact that roles 7 and 6 have the lowest priority.
Any help would be much appreciated
I'm pretty sure I might have solved this my self. The query I'm using is:
SELECT user_id, role_id, min(roles.priority)
FROM users_roles INNER JOIN roles
ON users_roles.role_id = roles.id
GROUP BY user_id

Search single entity which is presented by multiple rows SQL

I have User table which contains same user represented by different entities all around. For example
User Table
==========================
id name
1 John Doe
2 Doe, John
3 Nicholas Cage
4 BlackRiderXXX
5 Nicholas cage
where users John Doe, Doe, John, BlackRiderXXX are the same people. Also, Nicholas Cage and Nicholas cage are the same people. Other tables refer to user.id randomly based on which user object did the action.
For Action table it'll look like
Action Table
==========================
id user_id some_other_stuff
1 1 ...
2 2 ...
3 1 ...
4 4 ...
5 3 ...
Where the actions 1,2,3,4 are all done by John Doe.
I'll have these users merged by the user manually meaning we'd know who is whom. They'd also select which User is the one they'd like to be as their main user account so we need to know this information as well.
I'm simplifiying a bit but I have a dozen tables which are like the Action table I provided above. We have mainly two use cases on how we will need to query:
1) Find actions which are done by user X (which should check all the users entities belonging to user X)
2) Find actions and group unique users
Main point is we will be using it everywhere around the codebase on 100+ queries so we want to design it well. How can I construct a system where the query will be simple enough also powerful enough to handle different querying ways?
Thanks
PS: We are using PostgreSQL
Why not include the "main" user in the first table?
User Table
id name main_user_id
1 John Doe 1
2 Doe, John 1
3 Nicholas Cage 2
4 BlackRiderXXX 1
5 Nicholas cage 2
Then you would join on:
select . . .
from actions a join
users u
on a.user_id = u.id
where u.main_user_id = 1;
If you want this selectable per end user, then use a different table:
create table end_user_users (
end_user_users_id serial primary key,
end_user_id int references end_users (end_user_id),
end_user_user_id int references users (id),
end_user_main_user_id int references users (id)
);
Then the query would look like:
select . . .
from actions a join
end_users_users euu
on euu.end_user_user_id = a.user_id and
euu.end_user_id = $my_id
where euu.end_user_main_user_id = 1;
You can use regexp_replace(),initcap() and trim() functions to refine and extract the common name strings to be grouped, and then generate values for newly created action_id column depending on them :
with new_action0 as
(
select u.id as id,
case when strpos(u.name,',') > 0 then
initcap(trim(regexp_replace(trim(u.name),'(.*),(.*)','\2 \1')))
else
case when lower(trim(u.name))='blackriderxxx' then
'John Doe'
else
trim(initcap(u.name))
end
end as name
from action u
)
select n.id, dense_rank() over (order by n.name) as user_id
from new_action0 n;
Demo
A new decent user table can be created by using this query with create table .. as statement

Search a key word in the whole column of that table

I have two tables.
User table
UserId Username
1 User1
2 User2
3 User3
4 User4
17 User17
18 User18
20 User20
And One more
Customer-Support table
CSid Userslist
1 1,3
2 2
3 20,17,18
How can I get the userids of the User Table are not present in Customer-Support Table..
Using a recursive common table expression to split the values should do it:
;WITH Split AS
(
SELECT
LEFT(Userslist,CHARINDEX(',',Userslist)-1) AS Userslist
,RIGHT(Userslist,LEN(Userslist)-CHARINDEX(',',Userslist)) AS Remainder
FROM CustomerSupport
WHERE Userslist IS NOT NULL AND CHARINDEX(',',Userslist)>0
UNION ALL
SELECT
Userslist AS Userslist, NULL AS Remainder
FROM CustomerSupport
WHERE Userslist IS NOT NULL AND CHARINDEX(',',Userslist)=0
UNION ALL
SELECT
LEFT(Remainder,CHARINDEX(',',Remainder)-1)
,RIGHT(Remainder,LEN(Remainder)-CHARINDEX(',',Remainder))
FROM Split
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)>0
UNION ALL
SELECT
Remainder,null
FROM Split
WHERE Remainder IS NOT NULL AND CHARINDEX(',',Remainder)=0
)
SELECT * FROM Users
WHERE UserId NOT IN (
SELECT Userslist FROM Split)
The query will return User4 for your sample data as it's the only one missing in the CustomerSupport table.
Sample SQL Fiddle
I adapted my answer from this answer by KM. Credit to the one who deserves it.
The question is answerable with the current data-model, but it is a lot of work, complicated, and a sheer waste of time.
However, with a sensible data model, it is a very simple question, so I will answer it with such a model.
We remove the UsersList field from your Customer-Support table. It should never never never be there. No, really, never.
Now, assuming that, as your example data shows, every user can have one CSid, we will add a field CSid to your User Table. This is called a foreign key. Since, as you mention, not all users are linked to the CS Table, you make sure the field allows NULL values.
Now we fill in the data:
User table
UserId Username CSid
1 User1 1
2 User2 2
3 User3 1
4 User4 NULL
17 User17 3
18 User18 3
20 User20 3
And now, to answer your question:
SELECT * FROM UserTable WHERE CSid IS NULL;
Your question is a very good example why it pays to think about your data model before messing it up. Your query is extremely simple, if your data model makes sense.

Count rows of right table when joinning two tables using SQL Query

I have a question about SQL Query. Let me do the example to illustration my issue:
I have two tables like this:
Roles Table
ID Role Role Description
1 Administrator Someone in administrator board
2 User Someone who has an account
3 Guess Someone who just view the website
Users Table
ID Username RoleID
1 trind08 1
2 trind09 1
3 trind10 1
4 kimchi 2
5 linhchi 2
6 thanh01 2
7 thanh02 3
8 kiemanh 3
9 liemanh 3
My issue is I want to view all roles and count the user who resolve to them.
Result table after running the query might look like this:
ID Role Role Description Cound of User
1 Administrator Someone in administrator board 3
2 User Someone who has an account 3
3 Guess Someone who just view the website 3
My first try to create a SQL Query like this:
select rol.*, usrCout as 'Count of User' from Roles rol
left join (select count(*) from Users where RoleID == rol.ID) usrCout;
But my query run unsuccessfully and I can't get the result I want. Please help me for this.
Thank you
SELECT
ID
,ROLE
,Role Description
,(SELECT COUNT(*) FROM Users where RoleID = rol.ID) AS UserCount
FROM Roles rol
Try this query
Select count(*) as 'Count of User', r.RoleID, Role, Role Description from role r, Users u where u.RoleId = r.Id group by r.RoleID,Role, Role Description;
Fiddle
Hope this helps

Sql Server 2008 With Array

I have two tables in my sql:
Users :
id name roleid
1 David 1
2 Sean 2
3 Joe 1
Roles:
roleid desc
1 copy
2 delete
3 move
Now i use this cmd to select the user with the user permission
SELECT * FROM Users u INNER JOIN Roles r ON u.roleid = r.roleid
Now i want to know if it's possible to build SQL Table(Roles Table), that it's will be dynamically the number of roleid for each user. something like:
Users :
id name roleid roleid2 roleid3
1 David 1 2 3
2 Sean 2
3 Joe 1 3
Use an associative entity to address the many-to-many relationship between Users and Roles. A composite primary key in the UserRole table will prevent duplicate assignment of roles, and foreign keys referencing the Users and Roles table will preserve referential integrity.
See SQL fiddle for a sample implementation.
At first, I suggest you to use many to many relationship. It means trird table: UsersRoles (userid,roleid)
At second, it's impossible create dynamic number of columns in typical SQL statement. But its possible by using stored procedures.
here is working example
sqlfiddle