Ok, this is an ER model of what you have (lack of power):

Now let's focus on Calendar and SubCalendar. Clearly, you have a hierarchy. But how do hierarchies turn into tables? There are three general ways to do this:
1) Kill the parent and save the children . In this case, you delete the parent object and send all fields from this object to each of these children. In your example, you only have one child, so all parent attributes will be available only to him.
Advantages: No null values, since each table will have everything you need. No associations are required. If you run queries for only one type of children, this scheme will be useful because you will not need to filter by type, because each table will store only one type
Disadvantages: this scheme is not suitable for cases when you have overlapping children. In other words, if the parent row can have more than one child when sending fields to each child, the parent data will be duplicated for each child. Not good, so do not use this strategy if it is. In addition, if you have many children and very few records in each, you will have many tables with several records each, so it can become a little more difficult to manage

2) Kill the children and save the parent . In this case, you delete all children and send all your attributes to the parents. Since the parent is now a mixture of himself and all his children, he needs a way to determine which line belongs to that type of children. This is achieved by adding a new attribute to the parent object, which will determine the type of each row (regardless of the data type).
Advantages: for all children there will be only one table, so it is easy to manage. No associations are required. It may be useful if most of the queries that are performed in this table require results from more than one type of children.
Disadvantages: Again, if the parent can have a row related to several child data, it will be duplicated, since there will be one row for each of them, therefore there is a restriction in this solution. In addition, a new column must be added to the metadata. The volume of entries in the table will be more. Zero values should be tied to the data that children have, and to parents or other children.

3) Save everything : the least bloody decision is not to kill anything :) In this case, the hierarchy is replaced by the relationship between the parent and each of them. Thus, the child will need to connect to the parent table using a foreign key to access the parent data.
Advantages: No data duplication or null values. Each object has only a minimal amount of data, and the rest can be obtained by joining the parent table. In this case, the parent row can be associated with several children without duplication of data. If you run many queries that can be satisfied with only one table (usually the parent), this is a good option. Another thing is that it can be easily expanded to more calendars, for example, if you need to add a new calendar that requires new fields, you need to add a new table without changing the current
Disadvantages: Most tables are required (in fact, one is larger than the first). For each child, a connection is required that will degrade performance, the larger the data set. In addition, foreign keys are required to join both tables. If most queries require data from parents and children, this scheme will be the worst in terms of performance

Now you asked which database schema is best . I think it’s now clear that this depends on the requirements, the types of queries that will be executed, how the data is structured, etc.
However, I can analyze this a little more. You said that you have a calendar table, and sometimes more data is required for each of them. So, we can say that we have 2 types of calendars, parent and child. Therefore, we might think that switching to solution 2 is a good opportunity, because you will have 2 lines representing each type, but we were wrong. This is due to the fact that in this case, each child includes a parent. Now, if we can assume that if SubAttribute always non-empty for the child and null for the parent, we will even remove CalendarType , which will actually lead to solution 1.
Finally, as a rule (mainly because most queries have many associations in real life), if you want to focus on performance, you should go to solution 1, otherwise, if you want to focus on normalization, you should go to solution 3 .
I hope this resolves some doubts and may have caused others :)