Design a database to track the owner - php

In my business logic, I have a user, a company (users can be part of the company, as employees, i would call them "agents") and products.
A product can be owned by a user or by a company, the company can assign it to a user (agent) later, but it would still be owned by the company (in case the company fires the agent).
My thought is to have the user table, the company table and the product table and a table to track who is the owner of the product:
--------------
| users |
--------------
| user_id |
| name |
--------------
--------------
| products |
--------------
| product_id |
| title |
--------------
--------------
| company |
--------------
| company_id |
| name |
--------------
--------------
| agents |
--------------
| agent_id |
| user_id |
| company_id |
--------------
----------------
|product_owner |
----------------
| id |
| product_id |
| user_id |
| company_id |
|agent_assigned|
----------------
If the product is owned by a user then only product_id and user_id will be filled. If it's owned by a company, then product_id, company_id and agent_assigned would be filled.
Later, I would want to pull a product, and know who's the owner: the user info, or the agent and company info.
Is this the best way to do it? It doesn't seem that good to me.

Use the standard Party Model. Read up on Table Inheritance to implement it.
An asset is owned by a legal party. It could be an individual, group of individuals (say the Jones family), a government, a company. You need to abstract these concrete types to one abstract type so that you can point a single foreign key at them.

Based on your requirements I don't think you are too far off. I would separate the products that belong to company and user however and make it into something like this:
Then when you need to pull a product and find the owner you just need a join query. Something like this:
select * from product p
left join companyproduct cp on p.id = cp.product
join productowner po on cp.productid = po.productid
join agent a on po.userid = a.userid
where p.id = ? AND a.userid = ?
I'm not saying that syntax is correct or will work for you, it is just an example of what you would need to do.

Related

MYSQL better way to create category tables

I am trying create a schema for profile management system.
Since each profile will belong to different category for example sports,political ,non profit organization etc.
Each profile contain different info or details from one another so
1.My question is it better to create all columns in single table or creating different tables for each category because if i create in single category it will be large columns in mysql when category will increases or each category may come some related tables ?
users
id | first_name | middle_name | last_name | dob | primary_email | secondary_email | password | primary_phone | secondary_phone | home_address |
profile_categories
id | category_name |
user_categories
id | user_id | category_id
political
id | category_id | political_person_name | .....

"Has A" or "Belongs To" relationship or something else?

I'm not sure why I'm struggling with this it seems like a very simple concept. So my struggling makes me think that perhaps my data modeling needs another component...
I'm using Laravel 5 and am trying to define some model relationships. BelongsTo,HasA, etc. Before I can write the code, I need to at least conceptually understand what type of relationship I'm creating.
I have an application to where users can send people referral links, if a person clicks on the link and signs up, their user record makes note of the code that referred them. This way I can trace back and see who referred a particular user. But a referral is NOT necessary to sign up
Tables:
USERS
+----+-------------+
| id | referral_id |
+----+-------------+
| 1 | 1 |
| 2 | null |
| 3 | 2 |
+----+-------------+
REFERRALS
+----+---------------+---------+
| id | referral_code | user_id |
+----+---------------+---------+
| 1 | 12345 | 2 |
| 2 | 54321 | 2 |
| 3 | 99999 | 2 |
+----+---------------+---------+
USERS.REFERRAL_ID references REFERRALS.ID
and
REFERRALS.USER_ID references USERS.ID
But what kind of relationships are these?
The only one that seems obvious to me is that REFERRALS.USER_ID belongs to USERS.
But what about USERS.REFERRAL_ID, saying it belongsTo Referrals doesn't feel right, as that record isn't required and I don't feel like it 'owns' the user by any means. Saying it hasA referral doesn't feel correct either, as again the user doesn't own or even require the referral.
I guess what is confusing me is that REFERRALS is an optional entity.
How should I conceptualize the relationship between USERS.REFERRAL_ID and REFERRALS.ID?
Is it bad to have this sort of "circular reference"? Would I be better off creating a pivot table?
No need to add any reference to the Referrals table in the User table, you already have that relation defined in the referral table ( user_id column )
Further reading: https://en.wikipedia.org/wiki/Database_normalization
The Relationship is
USER has many REFERRALS
REFERRAL belongs to USER ( inviter )
REFERRAL belongs to USER ( invitee )
Modify your REFERRALS table
+----+---------------+---------+------------+
| id | referral_code | user_id | invitee_id |
+----+---------------+---------+------------+
| 1 | 12345 | 2 | 1 |
| 2 | 54321 | 1 | null |
| 3 | 99999 | 3 | 1 |
+----+---------------+---------+------------+
user_id is the id of the user that sends the invitation
invitee_id is the id of the user that accepts and registers
invitee_id column is nullable() and will contain the id of the invitee from users table when they join.
Think of it as a JOIN table between inviter and invitee.

Check if value exists in MySQL table and then select [Laravel 5]

Here is my pivot table project_group:
+-----+----------+------------+----------+---------+
| ids | group_id | project_id | admin_id | user_id |
+-----+----------+------------+----------+---------+
| 4 | 115 | 1 | 1 | [3,4,5] |
| 5 | 115 | 2 | 1 | [5,2,1] |
| 6 | 115 | 3 | 1 | [1,3,6] |
This table represent group linked to the projects....user_id is which users can see projects/group... Is there any way to display correct projects/group only to the users defined in user_id?
Also content in user_id field can be changed....
The best way to handle this would be to first normalize your database. Storing comma separated lists in a cell is allowed, but generally bad practice, as explained in this question.
If you can have multiple users per project, you should have a linking table with a column for project and a column for user, like this:
project_users:
| project_id | user_id |
and you can make (project_id, user_id) a composite primary key.
That way, you can select the users for a project (say, project 1) like this:
SELECT user_id
FROM project_users
WHERE project_id = 1;
Once you have these, you can display the project data only to users whose id is returned in the above list.
I have built an SQL Fiddle that helps demonstrate this visually, if it helps.
It is good to note that this proper normalization gives the opportunity to a lot of useful data as well, as it becomes easier to search for users by project, but also you can search for project information based on a user.

How should i store entities with only a few possible values?

How should i store data like users's gender, religion, political views which is selecting from a list of 2-8 max values like 'male', 'female' or 'orthodox', 'muslim','judaism','catholic' etc? Also this values is constant, even admin cannot change 'female' to something else. In a Database it looks wierd to store a similar tables with only this 2-8 values and make JOIN with a parent table on foreign key. Second way - special object inside program code - but it's always bad to mix program logic with a data.
Whether or not something is looking "weird" depends on personal preferences or design structures. However, it is entirely logical to store anything in a database that has to do with, well, data. Even a given set of options can change in the distant or not so distant future. I can't count the times a client asked me to change a set of options a day, a week, or even a few years after having ensured me that the set wouldn't change, ever.
Storing a list of options in a separate table is part of a relational database design. Relational database designs make it easy to get a set of data which includes or even excludes the options in any way in my opinion.
I'd recommend doing it the good, old fashioned way, for example:
Table user (id, user_name)
Table option (id, option_label)
Table user_option (id, user_id, option_id)
A user that is both male and catholic would have a relation with two options:
Table user Table option Table user_option
+----+-----------+ +----+--------------+ +----+---------+-----------+
| id | user_name | | id | option_label | | id | user_id | option_id |
+----+-----------+ +----+--------------+ +----+---------+-----------+
| 1 | john | | 1 | male | | 1 | 1 | 1 |
| 2 | melody | | 2 | female | | 2 | 1 | 6 |
| 3 | gerald | | 3 | orthodox | +----+---------+-----------+
+----+-----------+ | 4 | muslim |
| 5 | judaism |
| 6 | catholic |
+----+--------------+
Showing all selected options per user can be done with the following query:
SELECT `u`.*, GROUP_CONCAT( `o`.`option_label` SEPARATOR ', ' ) AS `options`
FROM `user` AS `u`
LEFT JOIN `user_option` AS `uo` ON `uo`.`user_id` = `u`.`id`
LEFT JOIN `option` AS `o` ON `uo`.`option_id` = `o`.`id`
It must go in a table, even if it make you makes joins. The join will be done over a PK, so there is little overhead

How to use data from a different table to obtain the appropriate records in MySQL

I have currently got a PHP generated calendar displaying some holidays for users. This information is stored in a database, I.e holidays and users. I want a user to be able to select a department and then AJAX will load the holidays for users only in that department.
Here are two made up tables with the same fundamental structure:
Table users
+------------------------------------+
| User | Department |
|------------+-----------------------|
| Brian | Sales |
| Tony | Marketing |
| Carol | Marketing |
| Dave | Warehouse |
| Chris | Warehouse |
+------------------------------------+
Table holiday
+------------------------------------+
| ID | User |
|------------+-----------------------|
| 1 | Dave |
| 2 | Tony |
| 3 | Tony |
| 4 | Chris |
| 5 | Carol |
+------------------------------------+
My current query:
$getAllHols = $con->query("SELECT * FROM `holiday`");
So of course, this just gets all holiday. I'm knowledgable enough on PHP to get a list of users in a specific department and then use that in another query to get holidays for those users. But I don't want to do this. I'm thinking there MUST be a pure-SQL solution. So I need the query to get all records from holiday where the user is in the selected department, using the two tables.
I.E:
If I chose the department "Marketing", records 2, 3 and 5 would be returned. (Tony and Carol are in Marketing).
Very easy problem for an advanced SQL user, I'm sure, but not to me. Can anyone help? Thanks.
Try this.
SELECT * FROM users
LEFT JOIN holiday ON users.user = holiday.user
WHERE holiday.department = 'marketing'
As far as I got...
select user
from users inner join holiday
on users.user = holiday.user
where department = 'Marketing'
This would provide a distinct list of records from the Holiday table if there are any matching records from the Users table. This improves upon the option of joining the tables, as you would not have to worry about de-duping the resulting data.
select distinct h.id, h.user
from holiday h
where h.user in (select u.user
from user u
where u.department = 'Marketing')
;

Categories