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

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.

Related

API paths for Many to Many relationship

I have the following entities on an Api:
Organization > OrganizationId (PK), Name, ...
User > UserId (PK), Name, ...
OrganizationEnrolment > (OrganizationId, UserId) (PK), EnromentTypeId
So OrganizationEnrolment has the enrolments of users in organisations.
An user can only have one enrolment per Organization so the PK (OrganizationId, UserId).
I have a few API endpoints like:
GET Organization = GET organizations/{organizationId}
Update Organization = PUT organizations/{organizationId}
Create User = POST users
Delete User = DELETE users/{userId}
The question is:
What should be the API urls to Create, Delete and Update an Organization Enrolment?
I am struggling with it ...
Get Organization Employees: GET organizations/{organizationId}/employees
Attach Employees to Organization: PUT organizations/{organizationId}/employees
Remove Employees from Organization without deleting Employees: DELETE organizations/{organizationId}/employees

SQL query to retrieve unique record based on role and email fields

I was trying to retrieve some records based on my requirement. As per the current table, a store can have any number of managers and/or cashiers with their respective email addresses. Now, I am trying to retrieve a new set of records which will have only one manager and/or one cashier per branch with their respective email address (there are no criteria to pick up specific manager cashier)
Current table:
BranchName Role Email
-------------------------------------------------
CA Cashier Cashier1#gmail.com
CA Cashier Cashier2#gmail.com
NY Manager Manager1#gmail.com
NY Manager Manager2#gmail.com
MASS Manager Manager#gmail.com
MASS Manager Massm#gmail.com
Expected output:
BranchName Role Email
------------------------------------------------
CA Cashier Cashier1#gmail.com
NY Manager Manager1#gmail.com
MASS Manager massm#gmail.com
The output is based on the requirement that, branch to Role is one to one mapping whereas Role to branch is one- many ( role and email forms a uniqueness for that particular branch).
I have tried using the below query but I am able to see the duplicate roles for a single branch.
select
BranchName, Email, Role
from
(select
BranchName, Email, Role,
ROW_NUMBER() OVER (PARTITION BY Role ORDER BY Email) AS "C"
from
Store
where
Role IN ('Manager', 'General manager', 'Cashier')
)
where
C = 1;
In my above query, while partitioning by role it only display single record with single branch instead of single role for all branches. It could be because of the condition C=1, if I remove this, I am getting all the records.
I hope, I have provided enough details. Kindly provide some inputs to fix this issue.
Thanks
If you don't have a preference/rule for choosing an email address given a branch name and role, then you just do a simple GROUP BY to get a result:
SELECT BranchName,
Role,
MIN(Email) AS Email
FROM Store
GROUP BY BranchName,
Role

SQL, a 'multi-tenant' issue: how to separate common data from user's data?

I have a SQL 'architectural' design doubt, so I ask about it here... Excuse me if it does make little sense, I'm quite new to SQL... :-(
UPDATE: As I did just learn thanks to a comment, this is a "multi-tenant" issue...
My app is a kind of a "contacts manager".
It will be used by some "user"s, who have access to some "person"s data.
Users and persons sets are disjoint.
Person's data is periodically populated by the app, server side.
Users can interact with persons data, adding - for example - some "notes", or some additional "phone" number.
The user-added data should be (RW) accessible only to the user who owns it, and not visible to other users; instead, the system-added data should be (RO) accessible to any user.
The interested tables are something like:
--------------------------
user
--------------------------
id | username | password
--------------------------
------------------------------------------------------
person
-------------------------------------------------------
id | key | name | age | sex | address | phone | notes
-------------------------------------------------------
The "id" fields are "integer autoincrement primary keys", while the "key" field is a unique identifier for the person.
The best solution I came up with until now is to add a new record for each user's data added, adding a "id_user" field to the person's table layout, where to store the id of the user who owns that record of data.
So the person's table should become:
-----------------------------------------------------------------
person
-----------------------------------------------------------------
id | key | name | age | sex | address | phone | notes | id_user
-----------------------------------------------------------------
(of course "common" data should have a "id_user" field content of null, or some special reserved value.)
I don't entirely like this solution, because it duplicates records for each person, so extraction queries will become more complex, and persons table will possibly grow very big...
I could think for example about using different schemas for different users, but I don't know if this is reasonable/feasible...
The question is: Do you consider this solution acceptable, and/or do you see any better alternative?
P.S.: I'm currently working with sqlite, but a standard SQL answer should be preferable...
I think, depending on how complex schema should be, there are several ways to improve it. In any system you should decide what data you will need to select, edit or delete commonly, it can really help to choose right model.
Complete separation users from persons:
users (id, username, password, name, age, sex, address, phone, notes)
persons (id, key, name, age, sex, address, phone, notes)
If you querying only users info or only persons info at a time, there is no purpose to join their info in one table.
Storing profile data in separate table:
users (id, username, password, profile_id)
persons (id, key, profile_id)
profiles (id, name, age, sex, address, phone, notes)
It can help querying for phones of all users and persons in one select without union.
Reverse depending:
users (id, username, password)
persons (id, key)
profiles (id, type, parentid, pname, age, sex, address, phone, notes)
where type is 0 for users, 1 for persons, parentid is id from users or persons. Sort of eav model, would help someone need several profiles.
If multiple profiles are in use (maybe future use) better way than 3. is to have transitional table:
users (id, username, password)
persons (id, key)
user_or_person_profiles (type, parentid, profile_id)
profiles (id, pname, age, sex, address, phone, notes)
It also can help with person, which is user too (maybe disjoint of persons and users is temporary).
Opposite to previous, you can join users and persons in one table
people (id, groupid, username, password, key, name, age, sex, address, phone, notes)
where groupid could be predefined const (0 for users, 1 for persons), or id from groups table, which can be used to build "group-role-permission" user rights system as complex as you need or imagine.
Again, what schema is better only you can decide, knowing what data and how often you will manipulate.
Hope, it will help somehow...

Multi Table Query Access Comparing Data

If I have three tables, one called Person, one called Owner and the other called Tenant. All three have SSN as one of the fields. What I want to do is compare the SSN from Person (that's the whole list) to see which ones do not show up in either OWner or Tenant so I can see which people in the database have never owned a unit or leased a unit. Then i would like to be able to delete these people out of the person table.
Thanks
One easy way to do this is using not in:
select p.*
from persons as p
where p.ssn not in (select ssn from owner) and
p.ssn not in (select ssn from tenant);

Database schema: how to implement feedback from users?

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