Database schema: how to implement feedback from users? - sql

I have table 'users'. Users can have roles - 'client' and 'employee'. Clients can give employees feedback (rating). I am not sure, how to implement it correctly, since clients and employees are one entity in schema (users).
I thought about something like this:
So, if a user has role 'client' then he will have feedback through 'given_feedback', and if 'employee', then through 'received_feedback'? Is it appropriate way to do it?
It is alike to this question: Database Design - Linking two users though in my case it is important to know who gave the feedback and who received it.

I would do something like this:
users
id
first_name
last_name
email
role_id
etc..
feedback_users
id
user_id
given_feedback - a value that tells if it's given (1) or recieved feedback (0))
feedback_text
roles
id
name
(two rows with client and employee)
Relations between above tables:
users.id - feedback_users.id (1 to many)
users.role_id - roles.id (many to 1) //given that a user can only have one role

Related

SQL Query: User/Group/Role and UserGroup/GroupRole Connecting User to Role

Good evening,
I have been struggling with what I think should be a fairly basic SQL query, but I can't seem to figure it out. Particularly because it seems as if there are multiple approaches (joins/ sub-queries).
I have three primary tables, and two tables connecting them.
USER
uID - PK
name, email, ...
GROUP
gID - PK
name
ROLE
rID - PK
permission
USERGROUP
uID - FK
gID - FK
GROUPROLE
gID - FK
rID - FK
These are many to many relationships, such that a user can be in multiple groups, and a group can have multiple roles.
I would like to have a query that ultimately gives me all of the roles that are connected to a given user through the groups that he belongs. Thus the uID is known, but nothing else. The output could have as few as one column with the rID, as that is all I really need for the program logic.
Is it possible to perform a query on the result of a previous query? I can easily find all the groups a user is in, and given each group, I can easily find the roles associated, but I get tripped up by the fact that there are many groups associated with a user, not just a single one which would be easier.
I would appreciate any help!
Thanks in advance.
This is just joins and aggregation:
select array_agg(distinct r.permission) as permissions
from usergroups ug join
grouproles gr
on ug.gid = gr.gid join
roles r
on gr.rid = r.id
where ug.uid = ?;
If you want the permissions in separate rows, then:
select distinct r.permission
from usergroups ug join
grouproles gr
on ug.gid = gr.gid join
roles r
on gr.rid = r.id
where ug.uid = ?;
I am leaving the distinct because different groups could share the same permissions.

SQL: Employee and Customer are Users, But not all Employees are Users

I'm trying to model a database for a rest server which is accessed via mobile app and web clients. Both Employees and Customers are users of the system. I have previously used composition rather than inheritance to design the database. I have used the design from this answer as such.
User (user_id, fullname, email, username)
Role (role_id, description)
UserRole (user_role_id, user_id,role_id, date_from, date_thru)
Customer (user_id, ...)
Employee (user_id, ...)
The problem is that to have an employee you need to have a user but not all employees are users i.e. I'm currently told to include drivers who are employees but not users of th system. So how can I create such a relationship?
You can have another composition level saying called "Person". So employees and customers are persons and persons could be users.
For the employees who are not user, you can have user_id equal to NULL.

Build a Query to get the informations from a specific user

I'm building a Chat with three Tables.
Conversation, Conversation_reply and user
Conversation Columns
id
user_one
user_two
Conversation_reply Columns
id
user_id
conversation.id
reply
User Columns
id
username
I would like to build a list with the name from the users that are chating with a specific user.
Example, my ID is 711, and I am talking with three persons, I would like to get the username from those three persons.
I'm having some issues building this Query because the user_one and user_two are relative, the ID from the receiver sometimes can be inserted as user_one, or user_two. It depends on which user starts chatting first.
How can I build a Query to do that?
Thanks.
Depending on your RDBMS you can check IF/ELSE, CASE/WHEN syntax.
Based on it you write statement:
SELECT if (user_one=711) user_two ELSE user_one
FROM conversation
where user_one=711 OR user_two=711
This is pseudocode, but idea should be clear.

How can I automatically add a foreign key to a table on select which is stored in an associated other?

I have a database with some tables among which these 3:
organizations
organization_id PK
teams
team_id PK
team_organization_id FK
users
user_id PK
teams_users
tu_id PK
tu_team_id FK
tu_user_id FK
So:
Team belongs to Organization
Organization has many Teams
User has and belongs to many Teams
Team has and belongs to many Users
And, consequently User has to belong to an Unique Organization. When I select some users, I would want to know (always) to which organization it depends.
What is the best way to deal with this ?
I think for now that perfect solution would be if I could get the organization_id called for example user_organization_id in my all select results on users.
Am I true on this point ? How to do that correctly ?
My database runs on PostgreSQL (9.3).
When I select some users, I would want to know (always) to which
organization it depends.
Use joins:
SELECT u.*, t.team_organization_id AS organization_id
FROM users u
JOIN teams_users tu ON tu_user_id = u.user_id;
JOIN teams t ON t.team_id = tu.tu_team_id
WHERE tu_user_id = $user_id;
To get that automatically, you could create a VIEW encapsulating the query:
CREATE VIEW usr_org As
<query from above>
Then instead of SELECT * FROM users, use:
SELECT * FROM usr_org;
More about views in the manual.

SQL Insert based on role

I have a database with 3 tables:
Table 1 (Department) - This is a table with columns for departments and departmentID's
Table 2 (SecurityMap) - This is a table that maps rolenames to department ID's
Table 3 (customer info) - this is the info that is displayed to users based on their role memberships
I have all of the SELECT based on role functions working.
What I need is to figure out how to insert a specific value into the DepartmentID column within Table 3 by default, based on the users role membership. For instance, when someone is adding a new row to the database - in addition to the data they are supplying within the "add" form, I need a default value inserted into this column. If they are a member of the Marketing role, it should be a 1, if they are a member of the IT role, it should be a 2, etc...
Ideally, this would be done without any knowledge to the user that it is even happening. I would assume that I need to use an "Instead Of" trigger, but I have no idea how to proceed....
Shouldn't be too difficult:
In your app, keep track of the logged-in user and their role.
When your app saves the customer data, make sure it passes the database the role ID as well as the user-entered data (a stored procedure would be ideal here)
When the database processes the supplied data, it saves the role ID into the appropriate column.
this should work provided the rolename-column (or id) is unique in the securityMap-table otherwise the select could return more than one value, maybe you need to select the departmentId differently then.
insert into customer_info(otherdata, departmentId) values('data', (select departmentId from securityMap where rolename = 'userrole'))
Edit:
since you mentioned db_owner maybe this can help you (from http://www.sqlservercentral.com/Forums/Topic411310-338-1.aspx)
WITH CTE_Roles (role_principal_id)
AS
(
SELECT role_principal_id
FROM sys.database_role_members
WHERE member_principal_id = USER_ID()
UNION ALL
SELECT drm.role_principal_id
FROM sys.database_role_members drm
INNER JOIN CTE_Roles CR
ON drm.member_principal_id = CR.role_principal_id
)
SELECT USER_NAME(role_principal_id) RoleName
FROM CTE_Roles
ORDER BY RoleName;
you could join that with the SecurityMap-table to filter out roles like db_owner