I have a big question about relationships in mysql. You see, I'm creating a site that looks like an e-commerce, it's for a colleague.
I am creating a table called categories and another called subcategories . In the subcategories table I have a column called categoria_id
, which will contain the ID of the selected category. Then like this, I will be able to show the subcategories with their respective categories.
An example: Cell Phone Accessories (category), Chargers (subcategory) and so on.
Is it necessary to create a relationship between the category ID, and the category_id of the "subcategories" table? I hope I have explained myself correctly.
Greetings.
If by necessary you mean mandatory , the answer is no , that is, you can create two tables and that, although they share information, they have no relationship with each other.
However, it is extremely advisable that you DO establish a relationship between the two and take care of the Referential Integrity of your data, since otherwise it would be technically possible to insert data from subcategories that do not have an existing category .
I'll pass you the MySQL documentation on Foreign Keys .
EDITED : I give you an example that will prevent you from having a subcategory without a parent category .
The truth is that I was surprised by @PatricioMoracho's answer, which helped me to reconsider a much simpler solution to the problem to understand and maintain . His answer opened my eyes to an important limitation of the previous model: the possibility of nested categories and sub-categories!
Interestingly, considering such complexity can lead us to solve the problem in a very simple way. It often happens that in life, what is complicated helps us to see that there is a simpler way .
Let's see:
Indeed, you can have a single table
categorias
to which we are going to add a new column calledpadre_id
. In that column we will put the id of the parent of each category. If it's a parent category, we'll set that value to zero (0
). That will help us to recover the main categories only, if we wish so...The code presents a simple query that will display each category and its children next to it.
Obviously, more complex queries could be made, such as one that shows each category and its sub-categories by levels, or code that reaches the grandparent category through its parent category.
Código:
Ver Demo
Resultado:
What is usually done in these cases is something like this.
Note: This is a basic example . It would be necessary to add the foreign key, referential integrity, indexes, depending on the type of database (InnoDB, MyISAM) in the table creation.
Since you're just starting out, and some have questioned that I haven't put anything about referential integrity in my answer , I want to tell you that before going any further, it's important to decide on the type of engine your tables will have.
In MySQL there are two:
MyISAM
eInnoDB
. Both have their advantages and disadvantages. For example this article (and others) can guide you: MyISAM or InnoDB? Choose your MySQL storage engineYou can also consult the official documentation of MySQL (in English):
MyISAM
InnoDB
The code presents a basic example and a query that would work if you want to get the sub_categories of a category x.
If you decide to do so , I
InnoDB
recommend that you read the documentation of said engine, and how the table creation syntax works, how the primary keys, the references, theon delete
, theon update
... etc. are indicated. It is a much broader topic than establishing a simple relationship. Depending on how you configure themon delete
, for example, the child data will be deleted when the parent is deleted, so as not to leave orphaned data. You need to learn how it works before implementing it...Código:
Ver Demo
Resultado
Juance, your question has already been answered, both A. Cedano's and David Isla's answers are valid. The issue is that I noticed a limitation in the model that you yourself were proposing, which is the category/subcategory model, and I asked you about it. Basically you can only manage two levels, you could not "hang" a subcategory from another subcategory, and in general only two levels of cataloging is usually not enough, just look at sites like MercadoLibre or others. My proposal is to handle a single table
categorias
without distinction, which in a certain way is reasonable since they are all categories and what changes is the hierarchy of how we want to see them, which will be handled by an attributenodo
. If at any time we need to move something or directly create a new level for all categories, this model is more flexible. It has an important complication : you have to take care of updating thenodo
, it is not complex but it has its logic.I extend A.Cedano's example a bit so you can see it:
The output would be something like this:
The indentation is just to visualize the hierarchy. Each product would have a
categoria_id
related tablecategorias
that would point to the predefined level within the tree. Searching for products below a certain category is very easy to implement, for example if you want all Cell Phone Accessories, you just have to indicate thecategoria_id = 2
. The maintenance of thenodo
if you are eventually going to create an ABM for it is not complicated but you have to be careful, such a structure is easier if the maintenance is done by script.In the example that I am proposing, each branch or node could hold up to 9999 categories, and up to 10 levels, but this is easily extendable by modifying the field
nodo
and the update logic. A somewhat more advanced model would be to manage some additional tablesjerarquia
andcategoria_jerarquia
to eventually manage different hierarchical models that depend on some criteria, for example "simple categories" or "extended categories" but I don't want to complicate your life, maybe this model will help you.Additional information: How do we add more categories?
First of all, I recommend keeping a first main category base on the first level, in the "Product Categories" example, any new item must always go below it, simply because later the logic to handle insertions is easier . Let's see an example: suppose we want to add a new mobile accessory "Chargers", how do we do it?
In the first place, you have to establish what the parent category is going to be, in this example it will be "Accessories for cell phones", in the query that I put together, I am not showing the ID but all the categories have an id, the one for Accessories is 2 , doing the following we will obtain the "parent" node and its length
The "parent" node is
00010001
the new item, we are going to insert it below this and at the end of the categories of that branch, so we need to calculate the final node, which would be something like this00010001????
, to calculate exactly the part of,????
we simply have to see what it is the last node of that branch and add one to it, like so:We are seeing the branch below the parent node, this because of it
LIKE '00010001%'
and also because we verify that the length of the node is 4 + the length of the parent node usingLENGTH(nodo) = 12
. The result would be:000100010004
, if you see the branch:It is clear that we must insert the new category as:
With this model, the insertions are always at the last level of the branch, eventually the logic could be built to reorder the items sequentially, making an "exchange" of the node between items, as for the
delete
, it is convenient that they be logical , using for example aFlagHabilitado
(1/0) but eventually they could also be physical.In some way, with the structure that you are proposing, you already have a relationship between categories and subcategories , but this is a mere reference, it is not physically in the database.
I consider it dangerous to use it without a physical relationship because the database will not manage the
integridad referencial
, also an index to that fieldconcepto_id
you declared will not be created and in the future it can create performance problems in query and update operations if you use that column as a criterion .In short, it is not necessary, but you assume unnecessary risks that you must cover from the programming.
I recommend reading about the
llaves primarias
andllaves foráneas
before everything to understand better.