What table structure would best fit this scenario? - mysql

I am developing an evaluation system for different programs that needs a lot of flexibility. Each program will have different things to track, so I need to store what data points they want to track, and the corresponding data for the person being evaluated on the particular data point. I am guessing several tables are appropriate. Here is a general outline:
Table: accounts
- unique ID assigned to each account. We'll call this 'aid'
Table: users
- each user with unique ID.
Table: evaluation
- each program will enter in the metrics they want to track into this table (i.e attendance)
- column 'aid' will correspond to 'aid' in account table
Table: evaluation_data
- data (i.e attendance) entered into this database
- column 'aid' will correspond to 'aid' in account table
- column 'uid' will correspond to 'uid' in user table
The input form for evaluation_data will be generated from what's in the evaluation table.
This is the only logical way I can think of doing this. Some of these tables will be growing quite large over time. Is this the most optimal way of doing this?

I'm a little confused about how accounts, users and programs all relate to each other and whether or not account and program are the same thing and that you used the terms interchangeably. I'm going to use different terms which are just easier for me to understand.
Say you have a website that allows freelancers to keep track of different projects and they can create their own data to track. (Hope you see the similarity)
Tables...
freelancers
id title etc
projects
id freelancer_id title description etc
data_options
id freelancer_id title
You can even add other columns like data_type and give options like URL, email, text, date, etc which can be used for validation or to help format the input form.
example data:
1 5 Status
2 5 Budget
3 5 Customer
4 99 Job Type
5 99 Deadline
6 102 Price
7 102 Status
8 102 Due By
This display 3 different freelancers tracking data, freelancers with the id's 5, 99, and 102. Deadline and Due By are essentially the same but freelancers can call these whatever they want.
data_values
id project_id option_id option_value
a column freelancer_id as you would be able to to a join and get the freelancer_id from either the project_id or the option_id
example data:
1000 1 2 $250
1001 1 1 Completed
1002 1 3 Martha Hayes
This is only showing information freelancer with the id 5 has input because option_id's 1-3 belong to that user.

Related

Better to have one master table or split into multiple tables?

I am creating a database and I am unsure of the best way to design my tables. I have a table of real estate properties and I want to store information about those properties - e.g. bedrooms, bathrooms, size... I may have additional information I want to store in the future if it seems useful - e.g. last purchase price or date built, so I need to be flexible to make additions.
Is it better to create a separate table for each "characteristic" or to have one table of all the characteristics? It seems cleaner to separate the characteristics, but easier programming-wise to have one table.
CHARACTERISTIC TABLE
id property_id characteristic value
1 1 bedrooms 3
2 1 bathrooms 2
3 1 square feet 1000
4 2 bedrooms 2
...
OR
BEDROOM TABLE
id property_id bedrooms
1 1 3
2 2 2
...
BATHROOM TABLE
id property_id bathrooms
1 1 2
...
Forgive me if this is a stupid question, my knowledge of database design is pretty basic.
I would suggest a middle ground between your two suggestions. Off the cuff I would do
property table (UID address zip other unique identifying properties)
Rooms table ( UID, propertyID, room type , room size,floor, shape, color, finish, other roo specific details ect..)
Property details (uid, propertyID, lot size, school district, how cost, tax rate, other entire property details)
Finally a table or two for histories eg.
Property sales history(UID, PropertyID , salesdate, saleprice, sale reason, ect..)
Often grouping your data by just "does it match" logic can yield you good results.... care needs only be taken to account for 1to1 and 1tomany relationship needs of tables.
I am focused to this:
"I have a table of real estate properties"
Now as far as i knew you has to be a different type of:
Houses
Bedrooms
Comfort room and so on.
For further explanation:
You has to be a table of:
1. House type
2. House names,description,housetypeid,priceid,bedroomid,roofid,comfortroomid and any other that related to your house.
3. Bedroom type
4. Comfort room type
5. Dining type
6. roof type if it has.
7. House prices
8. Bathroom type
something like that.
One table with a few columns:
Columns for price, #br, #bath, FR, DR, sqft and a small number of other commonly checked attributes. Then one JSON column with all the other info (2 dishwashers, spa, ocean view, etc).
Use WHERE clause for the separate columns, then finish the filtering in you client code, which can more easily look into the JSON.

How do I structure MySQL tables where one field could contain multiple values (but might not)?

I'm designing a web app which allows users to attend events and search for specific types of events.
Say, for instance, that these events are taking place in Hogwarts. The students have their own table where their studentID is held as a primary key, and this also contains which house they are a part of (of which there are 4), the subject they take, and which year of study they are in (e.g. 1 or 4 or 5, etc). The events can be for all students, specifically for 4th year students in the Ravenclaw house, or anywhere in between.
The events are held in an events table, which contains an eventID as the primary key, but I'm not sure how to hold the data for the house/year/subject it is aimed at. Obviously if an event were only aimed at 3rd year Hufflepuffs who take Potions, or something similarly specific, I could hold it within the same table. However, what if the event is for any year of Hufflepuffs (and not any Slytherins, etc)? Or if all students from all years, houses and subjects are eligible to attend? Will I need a table which holds all the years for each event and a separate table for which houses it's for and a further separate table for the subject it's aimed at?
Any advice or links are appreciated.
I think there are two ways but you definitely need at least one more table for the associations. Either you want to be very specific, about the combinations possible or you want to do it generally, like: only third years, only hufflepuffs, then the combination of the two values will be only third year hufflepuffs.
What I am trying to say are these two options.
1) One table that holds rows with very specific details:Event ID and the explicit combinations of all possible options (Here you will have a lot of rows)
This would mean that the event can be associated with second and third year hufflepuffs, but only second year slytherins.
association_id event_id year_id house_id subject_id
1 1 second hufflepuff potions
2 1 third hufflepuff potions
3 1 second slytherin potions
2) One table per property (here the disctinction is not as clear but you only have to create one row per property etc.
The following two tables could be used to store that all hufflepuffs and all slytherins that are in second or third year might attend
association_id event_id year_id
1 1 second
2 1 third
association_id event_id house_id
1 1 hufflepuff
2 1 slytherin
Does that answer your question or at least help you to find a solution?
Mybe if you can describe the target you are aiming at more closely one can find a solution suitable for your Problem together.

Database design for chatroom application

EDIT
People think this question is too broad so I'm narrowing things down a bit here:
I have a table with dual primary keys: roomID and userID.
Here is some example data:
roomID | userID
1 | 5
1 | 9
1 | 10
1 | 12
2 | 5
2 | 9
2 | 10
3 | 5
3 | 17
Given a list of users: 5,9,10, how can I return the roomID containing ONLY those users? So in this case it should return 2.
I hope this can be done within 1 SQL query.
Any help would be appreicated.
ORIGINAL QUESTION
I am making a chat room application and need to design a database backend for it. All the rooms are created on the fly and are destroyed when the last user exits the room. Users are able to add other users to any room they are in.
Currently this is my design:
I have a chatroom table with two columns. The two columns are both primary keys for the table (so a row is considered duplicate only when both columns are the same). The first column is the room ID. The second column is a user ID. The idea I have here is with the same room ID, there can be many users in this room (so rows with same room ID but different user ID). When I need to create a new room, I simply select MAX(room ID) + 1 and create a new room with this ID and add the users into it.
Given a list of users IDs (such as 1,5,31,12), I need to find out if a room is already created for them. In other words, I need to determine if there are rows all with the same room ID having users IDs 1,5,31,12. However, if a room is created with users 1,5,31,12,6 (one or more extra users), this should not count as room already created. I will then need to create a new room for them and add the users to that. Same goes for less users than the list.
Right now I'm having trouble forming the query to determine if I need to create a new room or not, and if not, retrieve the room ID of the existing room.
Any help would be appreciated.
Also, I think this design is quite cumbersome, you are welcome to suggest a better database design.
P.S. the database I'm using is MySQL
I think yoy can add 1 more col to the chatroom table, name num_member, this is number of member in room( or better have room(room_id, number_member) table). To make it simple first, I assume you have num_member in chatroom. This query might work:
Select * From chatroom where user_id IN ($userIdList) Group by room_id HAVING count(*) = chatroom.num_member
Hope this help

DB table creation -- breaking down age groups

I have a tutoring website where teachers list their preferences for the ages of their potential students.
So far, I have broken those ages into the following categories:
0-4, 5-9, 10-14, 15-19, Adults. These categories, I think, represent decent break points for students ages. But no matter -- the real issue is table creation.
I will make a secondary table, teachers_ages, with a foreign key for teacher_id and another column for age. Should I make this column an enum, with the following acceptable choices '0-4' '5-9', '10-14', '15-19', 'Adults'?. Is this somehow bad-practice (to group numbers with words?) Does it violate any database creation norms? Is there a better way to break age groups for use with CRUD?
Update: teachers can choose as many age groups as they want
Typically you would create a lookup table which would list an identifier and the associated value. For example
Lookup table (AgeRange)
ID Min_Age Max_Age Description
1 0 4 "Less than 4"
2 5 9 "5 to 9"
3 10 14 "10 to 14"
4 15 19 "15 to 19"
5 20 1000 "Adults"
Now you can add another table with the teacher id and the age range id. (There can be more than one entry in this table allowing teachers to have any number of preferences.)
When validating you join to this table and look at Min_Age and Max_Age. When reporting you use the Description field.
If each teacher can only choose one age group you do not need to add a second table. Put the age-group field in the teacher table. Set the datatype as varchar and use check constraints for your five choices.
Your approach is a valid way to break groups down into demographics, such as age, income, population, etc.

Count a specific value from multiple columns and group by values in another column... in mysql

Hey. I have 160 columns that are filled with data when a user fills a report form out and submit it. A few of these sets of columns contain similar data, but there needs to be multiple instance of this data per record set as it may be different per instance in the report.
For example, an employee opens a case by a certain type at one point in the day, then at another point in the day they open another case of a different type. I want to create totals per user based on the values in these columns. There is one column set that I want to target right now, case type. I would like to be able to see all instances of the value "TSTO" in columns CT1, CT2, CT3... through CT20. Then have that sorted by the employee ID number, which is just one column in the table.
Any ideas? I am struggling with this one.
So far I have SELECT CT1, CT2, CT3, CT4, CT5, CT6, CT7, CT8, CT9, CT10, CT11, CT12, CT13, CT14, CT15, CT16, CT17, CT18, CT19, CT20 FROM REPORTS GROUP BY OFFICER
This will display the values of all the case type entries in a record set but I need to count them, I tried to use,
SELECT CT1, CT2, CT3, CT4, CT5, CT6, CT7, CT8, CT9, CT10, CT11, CT12, CT13, CT14, CT15, CT16, CT17, CT18, CT19, CT20 FROM REPORTS COUNT(TSTO) GROUP BY OFFICER
but it just spits an error. I am fairly new to mysql databasing and php, I feel I have a good grasp but query'ing the database and the syntax involved is a tad bit confused and/or overwhelming right now. Just gotta learn the language. I will keep looking and I have found some similar things on here but I don't understand what I am looking at (completely) and I would like to shy away from using code that "works" but I don't understand fully.
Thank you very much :)
Edit -
So this database is an activity report server for the days work for the employees. The person will often open cases during the day. These cases vary in type, and their different types are designated by a four letter convention. So your different case types could be TSTO, DOME, ASBA, etc etc. So the user will fill out their form throughout the day then submit it down to the database. That's all fine :) Now I am trying to build a page which will query the database by user request for statistics of a user's activities. So right now I am trying to generate statistics. Specifically, I want to be able to generate the statistic of, and in human terms, "HOW MANY OCCURENCES OF "USER INPUTTED CASE TYPE" ARE THERE FOR EMPLOYEEIDXXX"
So when a user submits a form they will type in this four letter case type up to 20 times in one form, there is 20 fields for this case type entry, thus there is 20 columns. So these 20 columns for case type will be in one record set, one record set is generated per report. Another column that is generated is the employeeid column, which basically identifies who generated the record set through their form.
So I would like to be able to query all 20 columns of case type, across all record sets, for a defined type of case (TSTO, DOME, ASBA, etc etc) and then group that to corresponding user(s).
So the output would look something like,
316 TSTO's for employeeid108
I hope this helps to clear it up a bit. Again I am fairly fresh to all of this so I am not the best with the vernacular and best practices etc etc...
Thanks so much :)
Edit 2 -
So to further elaborate on what I have going on, I have an HTML form that has 164 fields. Each of these fields ultimately puts a value into a column in a single record set in my DB, each submission. I couldn't post images or more than two URLs so I will try to explain it the best I can without screenshots.
So what happens is this information gets in the DB. Then there is the query'ing. I have a search page which uses an HTML form to select the type of information to be searched for. It then displays a synopsis of each report that matches the query. The user than enters the REPORT ID # for the report they want to view in full into another small form (an input field with a submit button) which brings them to a page with the full report displayed when they click submit.
So right now I am trying to do totals and realizing my DB will be needing some work and tweaking to make it easier to create querys for it for different information needed. I've gleaned some good information so far and will continue to try and provide concise information about my setup as best I can.
Thanks.
Edit 3 -
Maybe you can go to my photobucket and check them out, should let me do one link, there is five screenshots, you can kind of see better what I have happening there.
http://s1082.photobucket.com/albums/j376/hughessa
:)
The query you are looking for would be very long and complicated for your current db schema.
Every table like (some_id, column1, column2, column3, column4... ) where columns store the same type of data can be also represented by a table (some_id, column_number, column_value ) where instead of 1 row with values for 20 columns you have 20 rows.
So your table should rather look like:
officer ct_number ct_value
1 CT1 TSTO
1 CT2 DOME
1 CT3 TSTO
1 CT4 ASBA
(...)
2 CT1 DOME
2 CT2 TSTO
For a table like this if you wanted to find how many occurences of different ct_values are there for officer 1 you would use a simple query:
SELECT officer, ct_value, count(ct_value) AS ct_count
FROM reports WHERE officer=1 GROUP BY ct_value
giving results
officer ct_value ct_count
1 TSTO 2
1 DOME 1
1 ASBA 1
If you wanted to find out how many TSTO's are there for different officers you would use:
SELECT officer, ct_value, count( officer ) as ct_count FROM reports
WHERE ct_value='TSTO' GROUP BY officer
giving results
officer ct_value ct_count
1 TSTO 2
2 TSTO 1
Also any type of query for your old schema can be easily converted to new schema.
However if you need store additional information about every particular report I suggest having two tables:
Submissions
submission_id report_id ct_number ct_value
primary key
auto-increment
------------------------------------------------
1 1 CT1 TSTO
2 1 CT2 DOME
3 1 CT3 TSTO
4 1 CT4 ASBA
5 2 CT1 DOME
6 2 CT2 TSTO
with report_id pointing to a record in another table with as many columns as you need for additional data:
Reports
report_id officer date some_other_data
primary key
auto-increment
--------------------------------------------------------------------
1 1 2011-04-29 11:28:15 Everything went ok
2 2 2011-04-29 14:01:00 There were troubles
Example:
How many TSTO's are there for different officers:
SELECT r.officer, s.ct_value, count( officer ) as ct_count
FROM submissions s JOIN reports r ON s.report_id = r.report_id
WHERE s.ct_value='TSTO'
GROUP BY r.officer