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

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.

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

Database structure suggestion (serialization or separate table)

I am currently making a database, and truth to be told I'm not exactly very good at it (kinda being forced to do it). Its a game database, and I have a table called game_table that I use for storing game sessions that users create.
The question is, what is the best way to store a list of invited users, requested users, confirmed users, declined users and pending users? Currently I am serializing the user IDs (e.g. invited users = "11235|2510|34630|45715|64530"). However, the main problem is that the field becomes not searchable, and it becomes a problem if I want to retrieve a list of games that a user is invited to. To solve that problem, I store a separate field in the user_table for invited_games (also serialized game IDs).
The problem with that, is that it is getting hard to maintain whenever I want to add new features, and it is too easy to make mistakes with keeping the serialized data in sync. Is it better to have separate tables like:
invited_users_table
Game_ID | User_ID
51 | 5193
51 | 10458
51 | 235
901 | 1536
901 | 4573
Or is there some other better way of storing these types of data? Please help, and thanks!
From what you say, it sounds like you need one table with three columns:
GameId
UserId
UserType
The latter would take on values such as "invited", "confirmed", "requested" and so on.
You would want separate tables if you had more information about the different groups. For instance, you might have a "who invited" column for invited users, or a "confirmation time" for confirmed users. If the number of specific columns needed for the different groups is large-ish, then you might want to think about a more complex data structure. If there are just a handful of such columns, you can add them into the table described above.
Yes, it is better to have a separate table for invited users.
Yet better would be to have game_user_relation table, which will store the game id, the user id and the relationship between them. Kinda:
create table game_user_relation(
game_id int not null,
user_id int not null,
relation_type varchar (10) not null,
primary key(game_id, user_id, relation_type)
) engine=InnoDB;
This table will allow one user to have many relations to one game.
Or, if you need to have exactly one user relate to one game - remove relation_type from primary key.
This way you could select all needed data from one table.

MySQL - Should every table contain it's own id/primary column?

I'm putting together a question and answers application - the answers are only going to exist as long as there is a question that relates to it.
So I've decided not to give the answers table it's own id column and have made the primary key a foreign key that relates to the question_id.
Questions table:
id | title
Answers table:
question_id | title
Should I keep it this way or give the answers table it's own id column?
If there is possibility of multiple answers for a single question then it will be better to have a primary key on answer table too to identify each row uniquely if we get duplicate answers as follows
id | question_id | title
1 1 5
2 1 5
3 2 true
But, in case you are anticipating only a single answer for each question then it is better to merge it to the question table as both question and answer are directly dependent on a single primary key.
id | question | answer
1 quest 1 ? 5
2 quest 2 ? 5
3 quest 3 ? true
4 quest 4 ? null
I hope, this clarifies your doubt.
To expound a bit on the two valuable comments that have been made, in my experience, the following is the most effective set of rules to follow when defining a database schema (I will give reasons after):
Create a Primary Key for each table
Create a surrogate key to be that Primary Key
When you have a one to many relationship (as you do in your questions & answers tables) include the PK from the one table (your questions table) in the many table (your answers table) NOTE: this is exactly as you have done it... except the answers table doesn't have it's own PK & surrogate key
When there is a many to many relationship between two tables create a linkage/join/relationship table which has a one to many relationship to your two tables (meaning you put the Primary Key of each table into the relationship table as a foreign key to the two tables, respectively)
REASONS (in the same order):
Primary key columns guarantee uniqueness for each row within the scope of the table itself (no other database object has to be involved & every row will be required to be unique). They also provide a default index in most databases, which speeds up table scans/queries. As, mentioned this effectively meets first normal form.
I've found surrogate keys to be a powerful & effective way to simplify both database design & relationships between tables. If you aren't familiar please read here: http://en.wikipedia.org/wiki/Surrogate_key
You have done this already, so I'm assuming you understand the benefits.
This is here simply to provide an example of how using surrogate keys as primary keys in every table can help you as a database schema grows. If you need to add other tables in the future you won't have to spend as much time & effort figuring out how to join them you already have all the keys you need to easily create a join table (for instance, if you later add users to the mix... users can be the author of either a question or answer OR both... this could get a little harry if you attempt to associate the SAME value to both the question & answers tables independently... in fact it won't work)

Storing key value where key repeats and using primary keys

I am in a situation where i have to store key -> value pairs in a table which signifies users who have voted certain products.
UserId ProductID
1 2345
1 1786
6 657
2 1254
1 2187
As you can see that userId keeps on repeating and so can productId. I wanted to know what can be the best way to represent this data. Also is there a necessity of using primary key in here. I've searched a lot but am not able to find the exact specification about my problem. Any help would be appreciated. Thank you.
If you want to enforce that a given user can vote for a given product at most once, create a unique constraint over both columns:
ALTER TABLE mytable ADD UNIQUE INDEX (UserId, ProductID);
Although you can use these two columns together as a key, your app code is often simpler if you define a separate, typically auto increment, key column, but the decision to do this depends on which app code language/library you use.
If you have any tables that hold a foreign key reference to this table, and you intend to use referential integrity, those tables and the SQL used to define the relationship will also be simpler if you create a separate key column - you just end up carting multiple columns around instead of just one.

Database many-to-many intermediate tables: extra fields

I have created a 'shops' and a 'customers' table and an intermediate table customers_shops. Every shop has a site_url web address, except that some customers use an alternative url to access the shop's site (this url is unique to a particular customer).
In the intermediate table below, I have added an additional field, shop_site_url. My understanding is that this is in 2nd normalised form, as the shop_site_url field is unique to a particular customer and shop (therefore won't be duplicated for different customers/shops). Also, since it depends on customer and shop, I think this is in 3rd normalised form. I'm just not used to using the 'mapping' table (customers_shops) to contain additional fields - does the design below make sense, or should I reserve the intermediate tables purely as a to convert many-to-many relationships to one-to-one?
######
customers
######
id INT(11) NOT NULL PRIMARY KEY
name VARCHAR(80) NOT NULL
######
shops
######
id INT(11) NOT NULL PRIMARY KEY
site_url TEXT
######
customers_shops
######
id INT(11) NOT NULL PRIMARY KEY
customer_id INT(11) NOT NULL
shop_id INT(11) NOT NULL
shop_site_url TEXT //added for a specific url for customer
Thanks
What you are calling an "intermediate" table is not a special type of table. There is only one kind of table and the same design principles ought to be applicable to all.
Well, let's create the table, insert some sample data, and look at the results.
id cust_id shop_id shop_site_url
--
1 1000 2000 NULL
2 1000 2000 http://here-an-url.com
3 1000 2000 http://there-an-url.com
4 1000 2000 http://everywhere-an-url-url.com
5 1001 2000 NULL
6 1001 2000 http://here-an-url.com
7 1001 2000 http://there-an-url.com
8 1001 2000 http://everywhere-an-url-url.com
Hmm. That doesn't look good. Let's ignore the alternative URL for a minute. To create a table that resolves a m:n relationship, you need a constraint on the columns that make up the m:n relationship.
create table customers_shops (
customer_id integer not null references customers (customer_id),
shop_id integer not null references shops (shop_id),
primary key (customer_id, shop_id)
);
(I dropped the "id" column, because it tends to obscure what's going on. You can add it later, if you like.)
Insert some sample data . . . then
select customer_id as cust_id, shop_id
from customers_shops;
cust_id shop_id
--
1000 2000
1001 2000
1000 2001
1001 2001
That's closer. You should have only one row for each combination of customer and shop in this kind of table. (This is useful data even without the url.) Now what do we do about the alternative URLs? That depends on a couple of things.
Do customers access the sites through
only one URL, or might they use more
than one?
If the answer is "only one", then you can add a column to this table for the URL, and make that column unique. It's a candidate key for this table.
If the answer is "more than one--at the very least the site url and the alternative url", then you need to make more decisions about constraints, because altering this table to allow multiple urls for each combination of customer and shop cuts across the grain of this requirement:
the shop_site_url field is unique to a
particular customer and shop
(therefore won't be duplicated for
different customers/shops)
Essentially, I'm asking you to decide what this table means--to define the table's predicate. For example, these two different predicates lead to different table structures.
customer 'n' has visited the web site
for shop 'm' using url 's'
customer 'n' is allowed to visit the
web site for shop 'm' using alternate
url 's'
Your schema does indeed make sense, as shop_site_url is an attribute of the relationship itself. You might want to give it a more meaningful name in order to distinguish it from shops.site_url.
Where else would you put this information? It's not an attribute of a shop, and it's not an attribute of a customer. You could put this in a separate table, if you wanted to avoid having a NULLable column, but you'd end up having to have a reference to your intermediate table from this new table, which probably would look even weirder to you.
Relationships can have attributes, just like entities can have attributes.
Entity attributes go into columns in entity tables. Relationship attributes, at least for many-to-many relationships, go in relationship tables.
It sounds as though, in general, URL is determined by the combination of shop and customer. So I would put it in the shop-customer table. The fact that many shops have only one URL suggests that there is a fifth normal form that is more subtle than this. But I'm too lazy to work it out.