Accessing Nested Parent Properties - mysql

I believe this is a relatively basic feature of SQL, but unfortunately I'm not managing to think of exactly how it's done, or what it would be called.
Basically, in my current database, we have Areas, which are parts of Districts, which are parts of Zones, which make up a Region.
Along this chain, each parent only has the ID of the next parent, however, I would like to generate a table with all Areas, where every Area has columns for the ID of the District, Zone, and Region of which it's part of. So how would I write this query?

Oracle offers hierarchical querying, where you can say something like
SELECT parent, child, LEVEL
FROM table
START WITH parent IS NULL
CONNECT BY PRIOR child = parent
The START WITH condition identifies the root of the hierarchy, and the CONNECT BY PRIOR clause identifies how to traverse the hierarchy.
MySQL doesn't have this capability, unfortunately.

Well, Laurence(in the comments) responded correctly, I've been out of the SQL game for a bit too long it seems.
So the simple answer would be:
SELECT child.id as ChildID, parent.id as ParentID, grandparent.id as GrandparentID
FROM child JOIN parent JOIN grandparent
WHERE child.parentID = parent.id AND parent.parentID = grandparent.id
Thanks to all who didn't hardcore downvote this terrible question.

Related

SQL Inheritance, get by ID

This question aims to get the most clean and "best" way to handle this kind of problem.
I've read many questions about how to handle inheritance in SQL and like the Table Per Type model most and would like to use it. The problem with this is that you have to know what type you are going to query to do the proper join.
Let's say we have three tables:Son, Daughter and Child.
This works very well if you for example want to query all daughters. You can simply join the child and get all the information.
What I'm trying to do is to query a Child by ID and get the associated sub class information. What I could do is to add a column Type to the child and select the associated data with a second select, but that does not seem pretty nice. Another way to do it would be to join all sub tables, but that doesn't seem to be that nice either.
Is there an inheritance model to solve this kind of problem in a clean, nice and performant way?
I'm using MySQL btw
Given your detailed definition in the comment with the use case
The Server gets the http request domain.com/randomID.
it becomes apparent, that you have a single ID at hand for which you want to retrieve the attributes of derived entities. For your case, I would recommend to use the LEFT JOIN approach:
SELECT age,
son.id is not null as isSon,
randomColumn,
daughter is not null as isDaughter,
whatEver
FROM child
LEFT JOIN son on child.id = son.id
LETT JOIN daughter on child.id = daughter.id
WHERE
child.id = #yourRandomId
This approach, BTW, stays very close to your current database design and thus you would not have to change much. Yet, you are able to benefit from the storage savings that the improved data model provides.
Besides that, I do not see many chances to do it differently:
You have different columns with different datatypes (esp. if looking at your use case), so it is not possible to reduce the number of columns by combining some of them.
Introducing a type attribute is already rejected in your question; sending single SELECT statements as well.
In the comment you are stating that you are looking for something like Map<ID, Child> in MySQL. Please note that this java'ish expression is a compile-time expression which gets instantiated during runtime with the corresponding type of the instance. SQL does not know the difference between runtime and compile-time. Thus, there is also no need for such a generic expression. Finally, also please note that in case of your Java program, you also need to analyse (by introspection or usage of instanceof) which type your value instance has -- and that is also a "single-record" activity which you need to perform.

Merging 2 tables horizontally

I have 2 tables Parents and kids in a MySQL DB, I would like to merge these 2 tables
I would like to know how to query both the tables so I get the following result (query), is this possible? if so, how could I do this?
Simple LEFT JOIN does the job
SELECT *
FROM Parents
LEFT JOIN kids
ON Kids.parents = parent.id
This should work(sort of):
SELECT *
FROM Parents
JOIN kids
ON parents.id = kids.parent
That will give you a result where each Child is on its own line though parents of multiple children will be repeated. This is probably a slightly nicer way of doing it. Your way is possible but it is a pain. You can find the answer on here, it is something that is asked fairly often.
Can I also suggest changing your structure?
I would suggest making a single name attribute for parent instead of father and mother and giving each represented person their own DB entry. Then give each kid a "motherId" and a "fatherId" instead of the combined "parents" attribute. Maybe also try to get into the habit of using "attribueId" attributes to clarify your relationships. This should give you a cleaner schema and be much easier to work with. As it is you have a coupled "parents" entity which needlessly links the father and mother or forces a null value to appear. If instead you have a "parent" entity you have much more freedom. It changes your logical 1 to 1 into a 1 to many.

How to get all grandchildren in one to many relationship HQL?

I currently have a MySQL table called Section, and each entry in Section has a bunch of rows in the News table. In each News entry, I have a bunch of rows in Comments table.
It's a many to one relationship between News and Section, and similarly many to one between Comments and News. This is a unidirectional relationship from the children.
This is probably very easy, but I'm new to HQL, how would I query for all the Comments for a particular Section? Is it a bunch of joins of recursive selects?
I apologize I don't know what this is called. Is it cascading?
The concept of cascading is about updating/inserting/removing a group of related entities , querying has nothing to do with the cascading in JPA /Hibernate
In your case , you can use fetch join to issue a single JOIN SQL to get all the children for a given parent .
The difference between fetch join and normal join is that fetch join will also cause all children objects to be initialized along with their parent in a single select such that you can avoid the potential N+1 problem when you loop through the children of the parent.
You can issue the fetch join using something like the following syntax:
from Section as section
left join fetch section.news as new
left join fetch new.comments

selecting element which refer to other elements in the same table

I am trying to build a very simple CMS. For that I have create a table called categories. As the name suggests it will be the categories for my articles in the CMS.
My table looks like follows with the sample data:
As you can see, a category node has a parent node. now, How can I write a query which selects all the parent nodes of a particular node. Example, if I choose, the node Important, how can I write a query which will return me the following nodes: News, Users, General
I hope I was clear enough
I can't say that I really love this method, but the following appears to work in MySQL:
select t.id, t.parent, #parent := parent
from (select #parent := 7) const join
t
on t.id = #parent;
You can see it in this SQL Fiddle.
I don't believe this is guaranteed to work, but it seems to work in practice. If you need to store hierarchical data, you should really change the data structure or switch to a database that supports recursive queries (Postgres, SQL Server, and Oracle, for instance).

Nested queries (dependent queries)

I need to store a family (i.e. some childs of a parent. Those childs have their own childs and so on..)
So, I created a table family that has following structure
id child child_id parent_id
When I save a child, I store a parent_id along with it.
Now,
when I want to fetch all childs of given parent, I can easily do.
select child_id from family where parent_id = <given parent id>
But,
now I want to fetch the complete family (all descendants of a given parent)
i.e.
I want to fetch all childs which have a given parent_id + all childs that are childs of fetched childs in first query and so on.
Can somebody help me ?
I also, thing there could be better way to store the data initially, so I can fetch it later. Can somebody point out a better way ?
You can write a query that will fetch a child and all of its dependants, but first you would need to re-design your table structure and a enforce a protocol when adding new children to make the query work all the time.
Take a look at this very useful article describing and explaining this method
use sub query
select GC.grandchildren,children from children C inner join grandchildren GC
on C.childid=GC.id and
C.childid in
(select child_id from family
where parent_id = <given parent id>)
Regarding your table design, I think your child_id column is redundant, you can just build the hierarchy by setting which is the parent_id of a certain node, and leave the parent_id empty for the root nodes.
Regarding the query for traversing all childs, you can use an approach like the one proposed here (http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/), but it wll mean you will need to follow some conventions in your ids and store a 'path' with each node.
(which will complicate things if you need to insert something in the middle ot the tree)
Other database brands have clauses for this problem (for Oracle, you have the STARTS WITH ... CONNECT BY clause), but none of them are ANSI.
Hope it helps