Create relational tables or store serialized data in a column? - php

I have a users table with this structure:
user_id | name | email | mobile
And another table called products with this structure:
product_id | name | price
now I want to add wish list to my project, so that a user can add some products into his wish list (with his favorite categories. Exmaple: add a wish list category called my favorite clothes and add product_id = 55 to that category)!
Now I have 2 options:
1. Add another colum to users table called user_wish_list and then store serialized data in that column like below:
$user_wish_list = [
'user_category_1' => ['product_id_1', 'product_id_2', ....] ;
];
and store serialize($user_wish_list) in user_wish_list column.
2. create 2 tables as below:
tabe: wish_list_categories
user_id | category_id (PK) | category_title
and
tabe: wish_list_items
category_id (FK) | item_id | product_id (FK)
and finally create a relation between these tables (By SQL join)
which option is better? I personally think the second one!
one of the reasons for my choice is that I can access to data with pure SQL query
like below (I do not have to process data after fetching from database by using unserialize() ):
SELECT users.user_id, users.name, wish_list_categories.category_id,
FROM Orders
INNER JOIN Customers ON users.user_id = wish_list_categories.category_id
But what about other advantages?
Or let me ask a more general question: when we exactly use relational tables instead of use column? (consider one-to-one relationship)

Use tables. In general, don't store structured data in individual SQL values. Let the tables and foreign keys produce the structure you need.

your tables should be like:
1- users table:
user_id|user_name|Email|price
2- products table:
product_id|product_name|category_id|price
3- products_category
category_id|category_name
4- user_wish_list table:
user_id|product_id

Related

Create JOIN for a many-to-many relationship

I can't get my head around JOIN and many-to-many database relationships.
I have 3 tables (structure has been simplified)
USERS:
id (primary) | userEmail | userName | userAddress | userCreated
TEAMS:
id (primary) | teamName | teamLogo | teamCreated
TEAMS-USERS
id (primary) | userId | teamId | userLevel
Teams can have many Users. And Users can be in many Teams. The UsersTeams table tracks which users are in which teams (note: I'm not using foreign keys or anything).
When a user logs in, I want to get a list of all the teams they are a member of and the corresponding data i.e.
get the data from USERS (where id = $id)
look it up in TEAMS-USERS
get the team information from TEAMS via the teamID in TEAMS-USERS
store it all in one array
I have this code so far but to be honest I'm just trying lots of variations:
$model->select('users.*, teams.*, teams.id as teamId, teams-users.id as teamsUsersId, teams-users.userId as teamsUsersUserId, teams-users.teamId as teamsUsersTeamId');
$model->where("users.id", $id);
$model->join('teams-users','teams.id = teams-users.teamId','inner');
$data = $model->get()->getRowArray();
Running the query above gives me the error: Unknown table 'myproject.teams' - even though the TEAMS table 100% exists and I use it throughout my project.
Where am I going wrong?
You get this error because in your query you are not including a from clause and you are missing a join clause. With codeigniter you can do that like:
$model->select('users.*, teams.*, teams.id as teamId, teams-users.id as teamsUsersId, teams-users.userId as teamsUsersUserId, teams-users.teamId as teamsUsersTeamId');
//$model->where("users.id", $id);
$model->join('teams-users','teams.id = teams-users.teamId','left');
$model->join('users','user.id = teams-users.userId and users.id='.$id,'left');
$data = $model->get('teams')->getRowArray();
explanation:
there was a missing join of table users
you want to use left joins
place the where clause inside the corresponding join (it becomes and)
you missed the from part, which can be done placing the table name in
the get() function or by $model->from('teams');
see also this nice explanation of joins

PHP function to return data from database as table with table relationships

I have a requirement for a PHP function that takes table or tables and the required columns from those db tables and returns a html table containing the data. I know how to do this for one table but am struggling with how to make this more dynamic
My thinking for one table would be to have a function that takes the table name and then an array of columns and then just selects the data from the table and then loops through it constructing the data as html and then return that from the function.
As an example my database has two tables; users and orders
users
|----------------------------|
|user_id|first_name|last_name|
|-------|----------|---------|
orders
|----------------------|
|order_id|user_id|total|
|--------|-------|-----|
Now with the function discussed above it would be easy to generate a table for all the users or orders but what I would like to do is have a function where I could dynamically join tables and for example list all users and the number of orders they've made or list all orders from user x. I know that this would be possible with many different functions but I'm really interested in developing a way of doing this dynamically and basically building all the relationships somehow in the program and then be able to call one function and request columns x,y and z
My thinking so far would be (again for this example) somehow define that number of orders for user i = count(order_id) where user_id = i
Hope this makes sense and thank you in advance
The INFORMATION_SCHEMA.KEY_COLUMN_USAGE table can be used to find all foreign key relationships from a particular table to other tables, e.g:
SELECT `TABLE_NAME`,
`COLUMN_NAME`,
`REFERENCED_TABLE_NAME`,
`REFERENCED_COLUMN_NAME`
FROM `INFORMATION_SCHEMA`.`KEY_COLUMN_USAGE`
WHERE `TABLE_SCHEMA` = SCHEMA() -- current schema
AND `REFERENCED_TABLE_NAME` IS NOT NULL
AND `TABLE_NAME` = 'orders'; -- name of table to get relationships to other tables
This should return something like the following:
+--------------+-------------+-----------------------+------------------------+
| TABLE_NAME | COLUMN_NAME | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+--------------+-------------+-----------------------+------------------------+
| orders | user_id | users | user_id |
+--------------+-------------+-----------------------+------------------------+
The above can be done in PHP and the results can then be iterated over to dyamically construct a query that selects from those tables, joining on the listed columns. Will leave that part as an exercise ;-)
You wouldn't need to make a function to grab data from first table then loop around them and get data from the second table.
SQL can do this for you with 1 hit on the database.
All what you need to do is join the two tables, and grab the data you want..
If I understood what you need right, you want to grab all users id from the first table, and get their order count from the second table.
A simple join or selecting from both table could do that, and I suggest something like:
Select a.user_id, b.count(order_id)
FROM table1 as a, table2 as b
WHERE a.user_id = b.user_id
Group By a.user_id
Or you could join the tables and do a similar task.
I am assuming you're gonna access database from PHP code, so try that, and give me back your feedback.
This is easy to implement but we have to fix few things.
Our requirement:
1. Identify Tables according to column name.
2. How we can Join those tables.
3. How to resolve ambiguity of columns.
Solution:
Unique column name for each field or no table has duplicate column name.
To achieve it we should have fix table prefix for each table.
for example:
your column name could be odr_orderid and usr_orderid.
Now by identifying unique prefixes, we can identify tables.
Now issue arises how to join these tables
To resolve it:
Create an another table strong JOIN keys and JOin type Left, right,inner or full.
Thats all Now you can make the query as you want.

How to query multiple tables and collate data

I am trying to make a notification list that displays notifications from multiple different content types and there respective database tables.for each content type There is a subscribe table with the respective subscriptions which I need to retrieve.the tables and there respective subscriptions tables are as follows
--------------------------
content type | subscriptions
-------------+------------
group | subscribegroup
-------------+------------
discussion | subscribediscussion
-------------+------------
forum | subscribeforum
-------------+------------
thread | subscribethread
-------------+------------
The problem I have is that each content subscription table has a different name for the id of its values eg
This is how I would get the data from one content a single table with its respective subscription table and then use UNION but isnt union heavy on the database server??
SELECT *
FROM thread t
JOIN subscribethread s ON (t.threadid = s.threadid)
WHERE userid= $currentuserid
How would I join multiple instances of other content types above with this? Thanks
We use JOIN when we need combine columns from few tables INTO ONE(or more) row. As i understand you need combine ROWS FROM DIFFERENT TABLES in one result table. There is no UNION alternative with such schemas structure.

Joining 2 Tables and show the same column repeatedly based on its associative ID

Hi i am not sure how to put this in a brief sentences, but i have DB table like the following
User Table
user_id
username
and so on...
Item
item_id
item_name
Item_Equipped
equipped_id head (FK to item_id)
hand (FK to item_id)
user_id (FK to user_id IN User Table)
I would like to generate a query that will display like the following format
user_id | head | head_item_name | hand | hand_item_name | ...
So far i only able to do this:
SELECT user.user_id, user.username,
equipments.head, equipments.head_acc,
equipments.hand,
equipments.acc, equipments.body
FROM gw_member_equipped AS equipments
LEFT JOIN gw_member AS user ON user.memberid = equipments.member_id
Which (i have to be brutally honest) doesn't do anything much.
I tried to perform INNER JOIN between item and item_equipped however i am unable to get individual name for each item (based on its item ID)
you need to join ITEM table two times with ITEM_EQUIPPED table.
you can use below query for your desired output column shown in question..
SELECT USER.User_Id,
Item_Equipped.Head,
Item_Heads.Item_Id Head_Item_Id, -- if you want you can remove this column
Item_Heads.Item_Name Head_Item_Name,
Item_Equipped.Hand,
Item_Hands.Item_Id Hand_Item_Id, -- and this column also as these columns are same as their previous select columns
Item_Hands.Item_Name Hand_Item_Name
FROM USER, Item Item_Heads, Item Item_Hands, Item_Equipped
WHERE USER.User_Id = Item_Equipped.User_Id
AND Item_Heads.Item_Id = Item_Equipped.Head
AND Item_Hands.Item_Id = Item_Equipped.Hand

How to select a users specific info from a MySQL database?

I was wondering how can I have my users pick their favorite food from a category of foods in my MySQL database.
Will I need two different tables? If so what will my second table look like?
Here is my MySQL food table structure.
id | parent_id | food | url
You'll need 3 tables in total:
Food - holds food information
Users - holds users information
Users_Food - holds user id + food id (and maybe a ranking)
You should probably read up on database normalization.
You'd need to make a second table:
user_id | food_id
Make them both primary.
Then you can use JOIN's to select the food:
SELECT f.food, f.url
FROM user_food AS u
INNER JOIN food AS f ON (f.id = u.food_id)
WHERE u.user_id = {USER_ID}
This will give you a list of all favorite foods set by the user.

Categories