Here's the problem:
The user will input his information on the required fields. Then the user will choose a selection in check boxes (the user can choose multiple) which will be saved in database (the value of the check box).
For example:
David selected 2 choices. Sports for example. David choose Basketball and Volleyball.
In my database, it would look like this:
| id | firstname | lastname | sports |
| 1 | David | White | Basketball |
| 2 | David | White | Volleyball |
My main problem is if I have to alter or delete the information, only one row will be altered or deleted which is a big problem. I can't make it like in explode or implode cause I have display the count of how many user have chosen a certain sport.
How am I able to solve this problem?
Looks like you need to normalize your table. You can create a table to store the person data:
person = (personid, firstname, lastname, other fields related to person)
and a table to store the choices:
sport = (sportid, name, other data related to sport)
And finally a table to manage the relationship:
PersonSport = (personid, sportid)
Then in the above scenario your data will be:
Person
personid Firstname Lastname
1 David White
2 Sam Black
and
Sport
sportid name
1 Basketball
2 Football
3 Tiddlywinks
and
PersonSport
Personid Sportid
1 1
1 2
2 3
2 1
To count how many users selected a sport:
Select count(*) from PersonSport where sportid = 1;
Related
I am currently working on a system which supports "custom fields" for users.
I will illustrate this with a simplified example of this database schema:
users
--------
user_id
name
age
custom_fields
----------------
custom_field_id
custom_field_name
user_has_custom_field_value
------------------------
user_id (FK to users table)
custom_field_id (FK to custom_fields table)
custom_field_value (column that contains value of custom field)
This schema supports creation of custom fields to store information as per what the customer wishes.
However, I want to list all users along with their custom fields in the query output (or by using some PHP logic)
| user_id | name | age | fav_sport | payment_mode | bank
----------------------------------------------------------------------------------
3 John 28 Football SWIFT Chase
6 Jane 24 Swimming Cash BOA
fav_sport, payment_mode and bank are custom fields created which are represented as 3 rows in the custom_fields table.
So, the custom_fields table looks like this :
custom_field_id | custom_field_name
-----------------------------------------------
1 fav_sport
2 payment_mode
3 bank
and the user_has_custom_field value looks like this :
user_id | custom_field_id | custom_field_value
----------------------------------------------------------------------
1 1 Football
1 2 SWIFT
1 3 Chase
2 1 Swimming
2 2 Cash
2 3 BOA
What is the best way to achieve this with minimum queries and without taxing the database ?
The only solution I can come up with is by using a query inside a for loop in PHP to fetch the custom fields (which will definitely be heavy). What are more efficient solutions to do this ?
Suggestions welcome for MySQL based, PHP based, Stored Procedures etc.
I'm trying to come up with some sort solution to a problem where I have to provide a user with dynamic dropdowns depending on the options they choose.
Currently I have 3 tables that are normalized as such.
Currently this works well with my HTML select elements, where if I select John Doe I would get Paul, Kevin and Dick as my second options and if I were to choose Kevin I would get Drake and Kanye as a third option.
My issue is that I do not want to keep creating tables since I would like to add more layers of staff_level in my application.
How would I approach this and have a fully dynamic table structure using PHP and MySQL?
Thank you for taking your time to read this.
You want an association table between the people. Put all of them in one table with unique IDs like so:
Table Staff
id | Name | <Other fields>
----+-------------+----------
1 | John Doe |
2 | Sam Smith |
3 | John Johns |
4 | Paul Pete |
5 | Kevin Mayor |
6 | Dick Ross |
...
Then the association table named whatever you like - maybe StaffHeirarchy:
Table StaffRelationships
id | ManagerId | SubordinateId
---+-----------+--------------
* | Null | 1 # Has no manager
* | 2 | 6 # Dick Ross is subordinate to Sam Smith
This table should have an id field for unique keys, but you don't have to care about what it is (it's not used as a Foreign Key as the Staff.id field is), which is why I put * there - in reality it would be some integer id.
I haven't seen your PHP for pulling values out of the database, but it is basically the same - query the association table filtering for the id of the manager you are looking for and you will get the ids of the subordinates (which you can JOIN on the staff table to get the names).
Basically, am working with a Human Resource Management application.
Positions (like trainer, deputy manager, manager, etc) are filled up based on their service.
There is a list of all employees, the one with highest service on any given date occupies the top-most position.
The number of key positions are fixed. Based on the employee's position in the list, his probable position will be displayed.
The positions are like:
(Position - Number of Posts)
Director - 1
Manager - 3
Dy. Manager - 5
Trainer - 10
Now, in the list of employees populated based on their experience, the first in the list will be the Director, next three will be Managers, following 5 employees will be Dy. Managers and next ten would be Trainers.
I want to design a database table for storing the positions and associated numbers. There may be possibility that new positions will be added and also, the number of positions may change with time. Example, if the number of Director posts are increased to two from one, it should be edited. As soon as the number of Director posts are edited, the first two employees in the list will be designated as probable Directors. The same logic holds good to all the other positions too.
Am not sure what should be the database structure for such a table. After done, I should be able to query the table using php for probable position of any given employee based on his rank in the employees list.
Example, if an employee is in rank 5, I should be able to query the table and get the probable position. In this case, rank 5 will be Dy. Manager.
Hope I have made my requirement clear. Please help me in designing a database table for this purpose.
Thank you!
Employees
=========
name | Boss
rank | 1
doj | 2010-01-01
"Select name from Employees order by rank, doj"
doj = date of joining
Is that what you mean?
rank could join to another table, where you store the readable rank title in order to generate title, name, etc
The existing employee database table consists of:
Employees
=========
name | Mark
doj | 2010-01-01
wrk | yes
"Select name from Employees where wrk=yes order by doj"
(this will remove employees in database who has left the company, with status wrk = no)
Lets say this will generate the results something like this:
Mark | 2010-01-01
Steve | 2010-02-01
Jack | 2010-04-01
Rick | 2010-09-01
David | 2010-12-01
Now, when I fetch the results and assign position based on their seniority (assuming positions manager=1, dy. manager=3, trainer=1) the result would be:
Rank | Name | Doj | Designation
1 | Mark | 2010-01-01 | Manager
2 | Steve | 2010-02-01 | Dy. Manager
3 | Jack | 2010-04-01 | Dy. Manager
4 | Rick | 2010-09-01 | Dy. Manager
5 | David | 2010-12-01 | Trainer
After some days, lets assume Jack quits the company (his wrk status will be no). So, the fetched results would look:
Rank | Name | Doj | Designation
1 | Mark | 2010-01-01 | Manager
2 | Steve | 2010-02-01 | Dy. Manager
3 | Rick | 2010-09-01 | Dy. Manager
4 | David | 2010-12-01 | Dy. Manager
As Jack quits, David gets promoted. The rank is just the serial number generated based on the number of rows fetched, auto increment.
Now, I wanted to create a table for the designation and number of positions, so that based on the rank, it fetches the designation.
I'm currently building an application that would recommend website base on their tag.
On my website when a user registers, it will fill out an interests. So this is a sample interest:
football, model trains, hockey
So this is separated by commas. So when the user clicks on register that will be saved in my database. This is the design of my database.
userID | name | interest
001 | John Doe | sports, model trains, hockey
So on the other hand, I also have users in my sites who uploads website URLs and also creates a tag related to it. So this is my database design for that:
postID | title | tags
001 | techcrunch.com | technology,softwares,startups
002 | nba.com | basketball,sports,all-star
003 | tmz.com | gossip, showbiz
So the logic for this one is that, I wanted to recommend NBA.com to user John Doe since NBA.com has a tag of sports and John Doe's interest has a sports tag.
Do you have any idea how to do that one? Just a follow up question, Is the database design correct or should I create a new table to store all the tags. Something like that (not sure though).
Your help would be greatly appreciated and rewarded! Thanks in advance! :)
I would have normalized the database so that you have tags in a separate table and relationship tables to connect with it. As such:
User table:
UserId Name
001 John Does
TagUserRelation
UserId TagId
001 001
Tag table:
TagId TagName
001 Sports
TagUrlRelation
TagId Url
001 nba.com
001 nhl.com
To increase performance I would have continued by creating indexed views with the necessary joins and implementing stored procedures to work with them.
An alternative, as mentioned, is full text search but this will be much slower and generally not considered good database design in this case.
this can be done by using full text search
refer here
You should create two separate table which hold single tags, several for each person or post.
You can create a multi-column primary key for it if you wish.
userID | interest
001 | sports
001 | model trains
001 | hockey
...
and the same way for posts:
postID | tags
003 | gossip
003 | showbiz
...
This greatly enhances your chances to write efficient SQL.
It would be much better to store the tags separately. So that you have a table for the tags and two more tables - one for the relationship between users and tags, and one for the relationship between posts and tags.
users
----------------------------------------
userId | name | password | ....
1 | John Doe | $p$fgA |
tags
--------------------
tagId | tagname
1 | basketball
2 | hockey
user_interests
----------------------------
id | user_id | tag_id
1 | 1 | 1
2 | 1 | 2
post_tags
--------------------------
id | post_id | tag_id
1 | 1 | 2
Then you use JOINs to get the required information
I have 3 mysql tables: events, artists and (artist) descriptions. All of them are in many-to-many relations.
Table 'events':
ID | eventTitle | etc.
-----------------------
1 | event 1 |
2 | event 2 |
etc.
Table 'artists':
ID | artistName | etc.
-----------------------
1 | artist 1 |
2 | artist 2 |
etc.
Table 'descriptions':
ID | artistDesc | etc.
----------------------------------
1 | artist 1 description 1 |
2 | artist 1 description 2 |
3 | artist 2 description 1 |
4 | artist 2 description 2 |
5 | artist 3 description 1 |
etc.
I made also junction tables events_artists and artists_desctriptions. Both of them have only 2 foreign keys and serve only for linking event, artist and description IDs.
Notice in my descriptions table - each artist can have many descriptions. That actually means that each description belongs to only one specific event. =)
If I do a query like this:
$q = "SELECT
events.*,artists.*,descriptions.*,events_artists.*,artists_descriptions.*
FROM
events,artists,descriptions,events_artists,artists_descriptions
WHERE
events.eventID = events_artists.eventID AND
events_artists.artistID = artists.artistID AND
artists.artistID = artists_descriptions.artistID AND
artists_descriptions.descID = descriptions.descID";
I will get all the descriptions for a particular artist. But none of descriptions will be aware which event they belong to...
What I want to display to user is something like this:
EVENT 1
artist 1 (artist 1 description 1)
artist 2 (artist 2 description 2)
EVENT 2
artist 3 (artist 3 description 6)
artist 1 (artist 1 description 3)
etc.
Should I make a junction table for event-description relation? If I do, I don't know exactly how to use it, uff! =)
Or maybe my problem isn't solvable with a simple query? Should I do something with php too? Sorry but I am totally confused =)
I hope I managed to explain my problem properly...
Thanks in advance for any help!
you should combine events_artists & descriptions tables to have only 1 table that links artist to an event and a description.
Can you modify the tables you already have? If so, and if each artist description can have only one artist and one event, then I would modify your schema to be:
Table event as is.
Table artists as is.
Table descriptions:
ID | artistDesc | artistId | eventId | etc.
------------------------------------------------------------------
1 | description of artist at event | 4 | 1 | ...
Then you can select all descriptions for an event with:
$query = "SELECT
events.*,artists.*,descriptions.*
FROM
events,artists,descriptions
WHERE
artists.artistID = descriptions.artistID AND
events.eventID = descriptions.eventID AND
events.eventID = $eventIdYouWant";
You can change the last row of that query to either events.event_name = $eventNameYouWant or artists.artist_name = $artistNameYouWant and it will work the same as if you were directly specifying the id.
you have already said its a relation between 3 tables .. so i think the answer is pretty obvious .. you need to have 1 table artist_id , event_id and description_id in ONE table instead of diving that into two tables like u have now.
I think you should alter your table structure, if you can.
It will result in a neater design.
Make a table, artist_event_description which contains all the IDs as foreign keys, instead of the two junction tables, it will help you to find out, to which event and artist a description belongs.
Another thing you can do is to include two more columns in the Description table, eventId and artistId (these will be foreign keys) and remove the junction tables. This way you will directly get all the information you need by just doing a SELECT over the description table.