schema design - best practise for storing survey data - mysql

Background:
I want to create a table for storing the questions and user answer in survey for research purpose.
The questions are multiple choices but only one answer can be selected.
The questions can be added or hided by users.
The questions are the same for every user.
Also, NO interviewer information is required to store because it is anonymous.
There is no absolute answer for the question because the choices are static for every question.
Table
Survey
-id(PKey)
-submittedDate
Question
-id(PKey)
-questionText
Answer
-id(PKey)
-answerText
Access Pattern
1.Find a survey with certain id with its questions and answers.
2.Calculate the distribution of the answer for certain questions, e.g. 50% people select answer a, 25% people select answer b for question 1.
Example
1 2 3 4 5
1. How much water do you drink today ✓
2. How many apples do you eat today ✓
My question
I have a rough design of the table and some fields, but I want to get some insight of how to relating these tables, and how should I design the schema using these 3 tables.
Update
Seems the Survey Table has been misunderstood.
Here is more concrete example.
Survey id 123
1 2 3 4 5
1. How much water do you drink today(questionId 1) ✓
2. How many apples do you eat today(questionId 2) ✓
Survey id 124
1 2 3 4 5
1. How much water do you drink today(questionId 1) ✓
2. How many oranges do you eat today(questionId 3) ✓
questionId 1 belongs to Survey id 123 and 124.
Survey id 123 have questionId 1 and 2.
So it is N-to-M relationship?

CREATE TABLE Surveys (
sid ... AUTO_INCREMENT,
other info about the survey (date, who took it, etc)
PRIMARY KEY(sid),
maybe other indexes
) ENGINE=InnoDB;
CREATE TABLE S_Q (
-- no AUTO_INCREMENT needed
sid ..., -- not AUTO_INCREMENT
qid ..., -- not AUTO_INCREMENT
answer VARCHAR(...), -- the actual answer (no need to normalization)
PRIMARY KEY(sid, qid),
INDEX(qid, sid)
) ENGINE=InnoDB;
CREATE TABLE Questions (
qid ... AUTO_INCREMENT,
question_text TEXT,
PRIMARY KEY(qid)
) ENGINE=InnoDB;
// This table may be unnecessary:
CREATE TABLE Answers (
-- no AUTO_INCREMENT needed
qid ...,
answer VARCHAR(...),
answer_description TEXT,
PRIMARY KEY(qid, answer)
) ENGINE=InnoDB;
(All columns should probably be NOT NULL.)
answer is the actual answer. It is short enough and self-descriptive enough not to need a lookup via an id.

you need to add to FKs on the question table which Survey it belongs to and on the Answer table for which Question this answer.
Survey
id(PKey)
submittedDate
Question
id(PKey)
questionText
Survey_id(FK)
Answer
id(PKey)
answerText
Question_id (FK)

Related

It is possible for a foreign key to store values that aren't matching primary key values? [duplicate]

This question already has answers here:
Many-to-many relationships examples
(5 answers)
Closed 3 years ago.
Database design question. Let's say I have two tables: [PEOPLE] and [FRUITS]:
[PEOPLE]
- id
- fruit_id
- many other columns
[FRUITS]
- id
- name
- many other columns
Which are related by PEOPLE.fruit_id = FRUITS.id.
So fruit_id can store any value from id of [FRUITS] table. But the problem is, I want fruit_id to store values besides those, like 'All of the fruits', 'Some of the fruits', 'None of the fruits'.
I already used NULL as a flag for 'None of the friuts' value.
What is the best solution in this situation?
And out of curiosity I wanna ask: What to do in the situation when I want one foreign key to store values of multiple primary keys? For example: there is one more table [VEGETABLES]:
[VEGETABLES]
- id
- name
- many other columns different from [FRUITS]
And I want PEOPLE.fruits_id to be able to store values from both FRUITS.id and VEGETABLES.id.
I am not native English speaker, so forgive me for mistakes.
Storing the fruit_id within the people table allows you to assign one or none (NULL) fruit to a person.
If you want to assign several fruits to one row in the people table you need a pivot table (one to many)
e.g
PEOPLE_FRUITS
- people_id
- fruit_id
- unique key people_id, fruit_id
This way you can assign none, one or many fruits to a row in the people table.
The unique key would disallow assignment of the same fruit to the same person multiple times.
Same applies to vegetables

Table 3 foreign key, either has a value and a null

So i have a users table. user can be author or a normal user. There's no defining column that says a user is an author, only in the story table where there's a foreign key(author_id = user.user_id).
Now i want to add a review function. User can review either a story and an author and can also rate a chapter.
So my table looks like this:
**review**
review_id(PK AI)
user_id(FK - user.user_id)//reviewer NOT NULL
author_id(FK - user.user_id)//reviewee NULL
story_id(FK - story.story_id)//reviewee NULL
chapter_id(FK - chapter.chapter_id)//reviewee NULL
**review_content**
review_content_id(PK AI)
review_id(FK)
rating decimal
content text
date_added datetime
Since user_id in the user_table, story_id in the story table and chapter_id in the chapter table are all PK AI. There is a 100% chance of duplicate/same values.
For example: user_id(5) reviewed author(10). user_id(5) also reviewed story_id(10), or user_id(5) rated chapter_id(10).
So to identify if a review is for a story/author/chapter. I plan to just null other FK and insert a value to the relevant FK.
If a review is for a story, then story_id(FK) will have a value meanwhile author_id and chapter_id will be null.
so in my query it will be:
//fetch review for story
$this->db->from('review');
$this->db->where('author_id', NULL);
$this->db->where('story_id', $story_id);
$this->db->where('chapter_id', NULL);
$this->db->get()->result();
I want to know if my table design is correct. Or should i stick to making different review tables(author,story,chapter).
I really wanted to write reusable methods for the 3 instead of making 3 for each types.
For example: checking whether review exists. Inserting reviews. fetching. etc. If i were to make 3 different tables then i would have to make 3 different methods for each functions.

MySQL: modeling for 90 yes or no questions survey with statistics support

I'm trying to design MySQL tables for survey.
The survey is composed of 6 sets of questions, 15 questions for each set, so total 90 questions. The questions and the order of questions are not gonna be changed, and there are some possibility for new set of questions(also 15 questions per set) to be added.
They are all 'yes or no' questions so the answers will be saved as true or false in boolean way.
I also save sex, nationality, age of users for statistics.
I wanna get the percentage of the same answers between two users.
I wanna get the percentage of the same answers between one person and majority(majority is the answer of more than 50%).
I wanna get the statistics of yes or no per question by combination of sex, nationality, age. For example, 66% answered yes for question no.11 or 12% of Korean women answered no for question no.86
So I made a table to support all those features
questions table
q_id PK(1 to 90)
q_text VARCHAR(100)
users table
u_id PK
sex TINYINT
nationality VARCHAR(20)
age TINYINT UNSIGNED
q_1 TINYINT
q_2 TINYINT
...
q_90 TINYINT
Is it okay to have 94 columns in one table? I'm afraid the number of columns will increase as I add some questions sets. So I splited answers to set table
set1 table
s_id PK
u_id users_table
q_1 TINYINT
q_2 TINYINT
...
q_15 TINYINT
set2 table
s_id PK
u_id users_key
q_16 TINYINT
q_17 TINYINT
...
q_30 TINYINT
and so on. I now have 6 set tables and I now can add new table if I add new set.
I searched a little about this and I saw that it would be better if I have a separate table for answers
answer table
a_id PK
u_id users_key
q_no question number(1~90)
answer TINYINT
I'm afraid that answers table may grow too big because answers table get 90 rows per user.
I'm really not sure which design is better. I've searched stackoverflow for answers but I couldn't find appropriate answer for yes or no survey.
Creating all those columns q_x is crazy, you just need to create a table called question_set with all the question like :
s_id PK
s_type (you can put 1, 2, 3 for set group)
q_id FK(questions)
You should normalize your table, putting all those columns will sooner than later create you problems. In the case you need to denormalize it is better to create views for that.
I would rather use foreign keys to make it more flexible.
So I would create
set_table
set_id PK
set_name Text
question_table
question_id PK
//This will help you put same question in multiple sets
question_set
set FK (set_table)
question FK (question_table)
user_table
user_id PK
user_name Text
sex Text
user_answer_table
user FK(user_table)
question FK(question_table)
answers Bool
Then you can write complex queries with joins to get all the metric you need. This will give you plenty of flexibility to add new questions, sets, users without the need to change the schema.

Stuck in database structure with many kind of tables [duplicate]

This question already has answers here:
How to design a product table for many kinds of product where each product has many parameters
(4 answers)
Closed 7 years ago.
I'm creating a structure of DB by E/R Diagram, but I'm stuck since some days on this problem. Probably I'm wrong in the way I'm doing it, so if you think I can do it in a better way, would be lovely :)
The scenario is:
I have N users who owns N sensors, not all the sensors (in the future could increase to 300 kinds of sensors) have the same features(columns), so I suppose I need a table for each sensor and then list the inside the values collected.
I have some doubts regarding how to referentiate the tabless for "kind sensor"-"Sensors" wich columns should I put on the "sensor" table, also in this way I will get many tables. Do yo have any hint?
Simplest and easiest way to do it is to make all specific columns in your table "sensors" and have one foreign key to another table "sensor_type" which is consisted of 2 columns
table "sensor_type"
id_type - identifier (primary key)
description - description of your sensor (heat, temperature sensor ... )
Your table sensor then looks like
table "sensor"
id_sensor identifier (primary key)
id_type foreign key references sensor_type table
size default null, if type 2 or 3 then something
weight default null, if type 1 and 3 then something
etc...
You need to understand this is probably one of many solutions which can solve your problem. I hope it helps.
May be it's better to introduce Many to many relationship between sensors and features they have? For example like this:
Sensors
sensor_id (pk)
type
Features
feature_id (pk)
name
SensorsFeatures (Ownership table)
sensor_id (foreign key to Sensors.sensor_id)
feature_id (foreign key to Features.feature_id)
If you need to store values of these features (weight, height, width,...) , you can do it in SensorsFeatures table.
You should add new table e.g. sensor_type for all sensors, where each row will be the sensor with uniq id which can be added to user.
The idea is to separate sensors with type or something else which is the most common thing beaten sensors.

Storing an array of arrays in mysql [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
I am making a table of a products like different types of vehicles: cars, trucks etc. They are made by an array of countries and each country has an array of makers, like Japan has Toyota, Honda, etc and US has Ford, GM etc. Once the database is built, I need to do operations like "select all vehicles made by Toyota".
What is the best way to store that?
The data structure is not necessarily the same as your array structure. The key word is "normalisation": design your tables in a way that avoids redundancies and make sure that each record in a table contains exactly the information that is relevant to describe the subject of that particular table.
A possible structure could be:
create table vehicles(
vid int auto_increment primary key,
void int,
vname nvarchar(32),
vtype int,
vmotor varchar(32), ...)
create table oem (
oid int auto_increment primary key,
oname nvarchar(32),
countryid int, ... )
The column void of table vehicles references the primary key oid of the oem (original equipment manufacturers) table.
A typical query can be the following:
select * from vehicles where
exists (select 1 from oem where oid=void and countryid=7)
countryid is just an integer key referencing yet another table (not listed here) containing country names etc.. Assuming that record 7 of the country table contains 'Japan' then the above query will list all vehicles made in Japan.
Or - coming back to your original example -
select * from vehicles where
exists (select 1 from oem where oid=void and oname='Toyota')
would list all vehicles of that particular manufacturer.
This little example is just the starting point for you to understand `normalisation'. Like Marc B already said: Study the concept for yourself and you will be able to answer your question yourself. Here is another example based link that might be helpful: http://db.grussell.org/section008.html .
Why not just have a table called Automobiles,
and then rows like Car, Model, Company,Country
and then you can just
SELECT * FROM Automobiles WHERE Company = 'Toyota' AND Country = 'Japan'