Database design - unique data from multiple sources - mysql

I have a table that stores information about pictures for automobiles. In a nutshell it contains the fields 'id', 'auto_id', 'name', and 'path'. So it is linked to a particular automobile entry through the 'auto_id' field.
Now consider that I want to add pictures for houses. Would it be better to just create another table similar to this one, or add a field in the existing table to point out the type of picture it is? Or is there an altogether better way to address this type of issue?
Edit: I apologize for the wording. It's obviously a simple problem, I just don't know how to best form it into a coherent question. Thanks for the patience and any help.

I would just model your picture table as:
id name path
and have a join table subjects table:
picture_id subject_id subject_type
Where picture_id is a FK to pictures, and subject_id is a FK to the specific subject deemed by subject_type(automobile, house etc)

Well, now given also that:
The 'id' field was just a unique identifier for the picture. The
'auto_id' field was the foreign key
for the automobile the picture was
linked to.
I would like to have it set up to
where one can have as many photos
linked to cars or houses as one would
like.
My suggested solution is:
Where
picture is your original pictures table, only that auto_id now is subject_id.
subject is your original automobiles table, now it will store both cars and houses records. Add a new field type_id as foreign key to subject types table.
subject_type is a new table where you'll store all possible subjects (not limited to cars and houses only, thinking to future expansion of your subject types).
(Sorry if this diagram doesn't reflect your real number/name/datatype of tables/columns, it's just that I don't know that info)

Given that only the subject (car or house) is what varies, and maybe in a future you will want to increase the number of subjects, I suggest you to keep all in one single table, just adding an extra field to store photo subject.
BTW: what is the difference between id and auto_id fields? If there is none, I'd suggest to get rid of auto_id column

Related

Understanding Primary Key and Relationship Databases with MySQL (phpmyadmin)

Forewarning - Something could be wrong from the start. More than one thing. Any additional help outside of the question I ask would be much appreciated :)
Also, admin_tbl can be ignored. It is simply usernames/passwords for administrators for the site.
Aim (and question): To create two relationship tables. Using my HTML Form I want to be able to insert information such as:
albumName - Exploration
name - Dead Sea
timeDate - 2015-12-21
comment - A beautiful landscape of the Dead Sea in Israel.
Upload Image - (button to choose image)
I have managed to create code (php and sql files) to upload the information into the database and upload the image into a 'Uploads' folder. However, the aim is for each album to have an ID (albumID), and to be able to have multiple images be uploaded and be a part of one album (along with having multiple albums of course, each with different images in). Can you help me do this?
What I have so far:
'image_tbl' - - Table which stores image path and the information from the form (including Album Name)
'album_tbl' - - Table which stores albumID and then albumName
Problems (I have run into):
image_tbl - As you can see each image I insert into the database is given an id, which is auto-incremented. Apparently, the auto-incremented id (unsure of official term) has to be the Primary Key. However, to have albumName (in this table) have a relationship in album_tbl doesn't it need to be the Primary Key?
album_tbl - In this table I have albumID and albumName. What I want is that when a form is inserted with an albumName (e.g. 'Exploration), for it to be also given the albumID. Therefore if I printed a specific 'albumID' every image placed into that would be shown.
Hope everything is understandable.
P.s. If you need any additional information just ask, and if you have recommendations to do this a lot easier/more efficiently, just tell me!
P.p.s If it can quickly be done, can someone explain what the 'Index' option is in the context of my tables (so it can easily be understood), thanks!
TL;DR You don't need to declare a "relationship" ie foreign key (FK) to query. But its a good idea. When you do, a FK can reference a primary key (PK) or any other UNIQUE column(s).
PKs & FKs are erroneously called "relationships" in some methods and products. Application relationships are represented by tables. (Base tables and query results.) PKs & FKs are constraints: they tell the DBMS that only certain situations can arise, so it can notice when you make certain errors. They are not relationships, they are statements true in & of every database state and application situation. You do not need to know constraints to update and query a database.
Just know what every table means. Base tables have DBA-given meanings that tell you what their rows mean. Queries also have meanings that tell you what their rows mean. Query meanings are combined from base table meanings in parallel with how their result values are combined from base table values and conditions.
image_tbl -- image [Id] is in an album named [albumName], is named [name], is dated [dateTime] & has comment [comment]
album_tbl -- album [albumID] is named [albumName]
You do not have to declare any PKs/UNIQUEs or FKs! But it is a good idea because then the DBMS can disallow impossible/erroneous updates. A PK/UNIQUE says that a subrow value for its columns must appear only once. A FK says that a subrow value for its columns must appear as a PK/UNIQUE subrow value in its referenced table. The fact that these limitations hold on base tables means that certain limitations hold on query results. But the meanings of those query results are per the query's table & condition combinations, independent of those limitations. Eg whether or not album names are unique,
image_tbl JOIN album_tbl USING albumName -- image [Id] is in an album named [albumName], is named [name], is dated [dateTime] and has comment [comment] AND album [albumID] is named [albumName]
The only problem here is that if album names are not unique then knowing an image's album's name isn't going to tell you which album it's in; you only know that it's in an album with that name. On the other hand if album names are unique, you don't need album_tbl albumID.
So if album names are unique, declare albumName UNIQUE in album_tbl. Then in image_tbl identify the album by some PK/UNIQUE column of album_tbl. Since album_id is presumably present just for the purpose of identifying albums, normally we would expect it to be chosen. Then in image_tbl declare that column as a FK referencing album_tbl.
PS Indexes generally speed up querying at the cost of some time and space. A primary key declaration in a table declaration automatically declares an index. It's a good idea to index PK, UNIQUE and FK column sets.
Welcome to relational databases.
The idea with relational databases is to have all data relate to each other but to avoid replication of data. This is called Normalization.
In your example you are replicating "Album Name" name in both tables, which is not necessary. What you want to do is change the column Album Name (in image_tbl) to Album ID and add a foreign key on album_id.image_tbl to album_id. album_tbl.

SQL Structure for several tables

I need to create a mySQL database that keeps information about vehicles. My instincts were to create one table with as many columns as I need, but then I read about the problems in doing so. After researching, I think I'm on the right track with the following structure:
Vehicles Database
Motorcycles Table
id|road|cruising|touring|
Cars Table
id|sedan|coupe|hatchback|
Colours Table
id|green|red|blue|black|silver|white|yellow|etc..
Make Table
id|ford|chevrolet|gm|toyota|bmw|etc..
Quadrant Table (1-4)
id|motorcycle|car|truck
So basically I have a table for the objects - cars, motorcycles, trucks - and then tables for the fields/properties - Colour, Make, etc. and then a table for the Quadrant the vehicle is seen in, with a value of 1-4 where each row is an instance of only one vehicle.
The problem I'm having is understanding where the primary and foreign keys need to be in order for me to be able to organize the data:
By each individual vehicle selected along with its fields
By quadrant, showing each vehicle and their respective fields
The user counting cars should be able to input the vehicle type, the field values and the quadrant it's seen in and the db gets populated - and then I need to call the data by quadrant to analyze the data.
I don't know if or how a JOIN statement will be used? How do I go about structuring this database to suit my needs?
FWIW, dba.stackexchange says basic SQL questions belong here, so I hope I'm in the right place.
Can you tell, what is your exact need for the database i.e what functionality you need.
I suggest tables like following:
1) Vehicle table:
id|type which might contain info like 1|Motorcycle, 2|Car
2) category table:
id(foreign key)|category|color which contain info like 1|touring|Black, 2|Car|Hatchback
3) Make table: (if you need to create another table)
id (foreign key to table 1)|Make
I have not understood the functionality of quadrant table but with these 3 table you can create views according to your needs and play around with it.
From my point of view:
I will create a table CarBrands, with columns Id, BrandName, Description, which will serve as a look up.
Then I will create another table Cars with Id, CarBrandId, ColorId (From Colors Table), Description, which is your table with user records.
Same with your other entities. I suggest you search about Entity Relationship Diagrams, a good way of helping you come up with a good design.
Also look at this old StackOverflow question, this will help you.

Model a table that can have a relationship with several tables

I have a table called 'notes', on this table I need to track who made that note, but the problem is that the creator of the note can be a user stored in one of three possible tables:
users
leads
managers
I have though of simply create three fields on 'notes' to represent the three possible relations: note.user, note.lead, note.manager
With this approach I would be forced to create three table joins when requesting the notes to gather the creators information, and I don't think that is the way to go, so I would like to hear your ideas or comments and what would be the best approach on this.
For me personally this smells like a design problem on a totally different part of the schema: Are manageers not users? Do leads carry person information?
With any approach that creates a relation between one column and one of three others, you will need three joins for the select. If you can't rectify the underlying problem, I recommend you use
note_type ENUM('users','leads','managers')
as an additional field and
SELECT
...
IFNULL(users.name(IFNULL(managers.name,leads.name))) AS name
..
FROM notes
LEFT JOIN users ON notes.note_type='users' AND users.id=notes.note_source
LEFT JOIN managers ON notes.note_type='managers' AND managers.id=notes.note_source
LEFT JOIN leads ON notes.note_type='leads' AND leads.id=notes.note_source
...
for the query
I think you need to abstract out the concept of a user id, so that it does not depend on their role. The author of a note could then be specified by the user id.
Users could be assigned roles, and maybe more than one.
The correct way to structure this would be to pull all common data out of users, leads, and managers. Unify this data into a "contact" table. Then if you want to get all notes for a given manager:
managers->contacts->notes
for a lead:
leads->contacts->notes
Notice your original post: "the problem is that the creator of the note can be a user stored in one of three possible tables"
From the structure of your sentence you even admit that all these entities have something in common; they are all users. Why not make the DB reflect this?
you have to model a parent table for the three tables you already have. Define a table that depicts generally user, leads and manager tables. Something like "Person". So you have all of the ids of the three tables and any common attributes on the Person table. And when you must define the relationship you put the foreign id "Person_ID" on the note table. And when you model user, leads and manager tables you also put the primary key as a foreign key to the Person table.
So you would have something like this:
Table users:
Users(
person_id primary key
...(attributes of Users)
foreign key person_id references Person.person_id
)
This model i depict is common to any relational model you have to model using parents and childs

Shared Primary Key

I would guess this is a semi-common question but I can't find it in the list of past questions. I have a set of tables for products which need to share a primary key index. Assume something like the following:
product1_table:
id,
name,
category,
...other fields
product2_table:
id,
name,
category,
...other fields
product_to_category_table:
product_id,
category_id
Clearly it would be useful to have a shared index between the two product tables. Note, the idea of keeping them separate is because they have largely different sets of fields beyond the basics, however they share a common categorization.
UPDATE:
A lot of people have suggested table inheritance (or gen-spec). This is an option I'm aware of but given in other database systems I could share a sequence between tables I was hoping MySQL had a similar solution. I shall assume it doesn't based on the responses. I guess I'll have to go with table inheritance... Thank you all.
It's not really common, no. There is no native way to share a primary key. What I might do in your situation is this:
product_table
id
name
category
general_fields...
product_type1_table:
id
product_id
product_type1_fields...
product_type2_table:
id
product_id
product_type2_fields...
product_to_category_table:
product_id
category_id
That is, there is one master product table that has entries for all products and has the fields that generalize between the types, and type-specified tables with foreign keys into the master product table, which have the type-specific data.
A better design is to put the common columns in one products table, and the special columns in two separate tables. Use the product_id as the primary key in all three tables, but in the two special tables it is, in addition, a foreign key back to the main products table.
This simplifies the basic product search for ids and names by category.
Note, also that your design allows each product to be in one category at most.
It seems you are looking for table inheritance.
You could use a common table product with attributes common to both product1 and product2, plus a type attribute which could be either "product2" or "product1"
Then tables product1 and product2 would have all their specific attributes and a reference to the parent table product.
product:
id,
name,
category,
type
product1_table:
id,
#product_id,
product1_specific_fields
product2_table:
id,
#product_id,
product2_specific_fields
First let me state that I agree with everything that Chaos, Larry and Phil have said.
But if you insist on another way...
There are two reasons for your shared PK. One uniqueness across the two tables and two to complete referential integrity.
I'm not sure exactly what "sequence" features the Auto_increment columns support. It seem like there is a system setting to define the increment by value, but nothing per column.
What I would do in Oracle is just share the same sequence between the two tables. Another technique would be to set a STEP value of 2 in the auto_increment and start one at 1 and the other at 2. Either way, you're generating unique values between them.
You could create a third table that has nothing but the PK Column. This column could also provide the Autonumbering if there's no way of creating a skipping autonumber within one server. Then on each of your data tables you'd add CRUD triggers. An insert into either data table would first initiate an insert into the pseudo index table (and return the ID for use in the local table). Likewise a delete from the local table would initiate a delete from the pseudo index table. Any children tables which need to point to a parent point to this pseudo index table.
Note this will need to be a per row trigger and will slow down crud on these tables. But tables like "product" tend NOT to have a very high rate of DML in the first place. Anyone who complains about the "performance impact" is not considering scale.
Please note, this is provided as a functioning alternative and not my recommendation as the best way
You can't "share" a primary key.
Without knowing all the details, my best advice is to combine the tables into a single product table. Having optional fields that are populated for some products and not others is not necessarily a bad design.
Another option is to have a sort of inheritence model, where you have a single product table, and then two product "subtype" tables, which reference the main product table and have their own specialized set of fields. Querying this model is more painful than a single table IMHO, which is why I see it as the less-desirable option.
Your explanation is a little vague but, from my basic understanding I would be tempted to do this
The product table contains common fields
product
-------
product_id
name
...
the product_extra1 table and the product_extra2 table contain different fields
these tables habe a one to one relationship enforced between product.product_id and
product_extra1.product_id etc. Enforce the one to one relationship by setting the product_id in the Foreign key tables (product_extra1, etc) to be unique using a unique constraint.
you will need to decided on the business rules as to how this data is populated
product_extra1
---------------
product_id
extra_field1
extra_field2
....
product_extra2
---------------
product_id
different_extra_field1
different_extra_field2
....
Based on what you have above the product_category table is an intersecting table (1 to many - many to 1) which would imply that each product can be related to many categories
This can now stay the same.
This is yet another case of gen-spec.
See previous discussion

Users table - one table or two?

i wanna have a Users details stored in the database.. with columns like firstname, last name, username, password, email, cellphone number, activation codes, gender, birthday, occupation, and a few other more. is it good to store all of these on the same table or should i split it between two users and profile ?
If those are attributes of a User (and they are 1-1) then they belong in the user table.
You would only normally split if there were many columns; then you might create another table in a 1-1 mapping.
Another table is obviously required if there are many profile rows per user.
One table should be good enough.
Two tables or more generally vertical portioning comes in when you want to scale out. So you split your tables in multiple tables where usually the partiotioning criteria is the usage i.e., the most common attributes which are used together are housed in one table and others in another table.
One table should be okay. I'd be storing a hash in the password column.
I suggest you read this article on Wikipedia. about database normalization.
It describes the different possibilities and the pros and cons of each. It really depends on what else you want to store and the relationship between the user and its properties.
Ideally one table should be used. If the number of columns becomes harder to manage only then you should move them to another table. In that case, ideally, the two tables should have a one-one relationship which you can easily establish by setting the foreign key in the related table as the primary key:
User
-------------------------------
UserID INT NOT NULL PRIMARY KEY
UserProfile
-------------------------------------------------------
UserID INT NOT NULL PRIMARY KEY REFERENCES User(UserID)
Depend on what kind of application it is, it might be different.
for an enterprise application that my users are the employees as well, I would suggest two tables.
tbl_UserPersonallInformation
(contains the personal information
like name, address, email,...)
tbl_UserSystemInformation (contains
other information like ( Title,
JoinedTheCompanyOn,
LeftTheCompanyOn)
In systems such as "Document Managements" , "Project Information Managements",... this might be necessary.
for example in a company the employees might leave and rejoin after few years and even they will have different job title. The employee had have some activities and records with his old title and he will have some more with the new one. So it should be recorded in the system that with which title (authority) he had done some stuff.