What is the most efficient way to delete hierarchies in mysql - mysql

I am using a modified version of adjacency list to store hierarchical data. So a tree of this sort is created.
The same is represented in mysql schema in this way :
What is the best way to delete a node in between say C so that the children F, G are now children of A ?

At application level you'll need to list down the childs of the node to be deleted and assign those childs' levels columns to parent node.
You can otherwise create a trigger on delete of node from the table which will do the above task.
If you would have structured your table correctly your all tasks would have been much easier.
table should have been just a parent child relation where immediate parent is saved.
Id Name ParentId
1 A NULL
2 B 1
3 D 2
levels can be determined by the no. of times recursion is done.
you can even do that now by adding the parent column and writing a script which would add the last levels available in the column.
So in this case, deletion would be simply
1. get list of childs - where parentid=nodeid.
2. updating their parent column with nodeids' parentid.
instead of updating and calculating all 3 level columns.

Related

Ordering items in database

I'm searching for an efficient way to add order the inserted item in a table in a database.
I'm thinking of two ways to strategies to achieve it.
First strategy:
to add order column in the table, and maintain its consistency with every Create, Update, and Delete (its very costly method) especially when I need to change the order, I need to change all elements after the updated element.
item order
1 2
2 1
3 4
4 3
Second strategy:
to make a meta_data table for all metadata and save the order and id of the product.
for example:
'products' => [{id:1, order:2}, {id:2:order:1},......]
I can replace the metadata list with each modification, but it is also a costly method when selecting data from a table.
Are there any more efficient way.
If you are insistent on ordering correctly after every edit, create a view like so:
CREATE VIEW ViewerData AS
SELECT * FROM Products
ORDER BY Id
Then use the view as your back end table, whilst you are still able to update the actual table - by using the view instead of the table, it will automatically reorder every time you requery.

Twitter-like database table structure

I am trying to create a database that can be used like Twitter works. That is:
Treestructure: Any node can have multiple childnodes.
All nodes have a timestamp
Criteria 1 and 2 suggests a table structure based on basic columns something like:
NodeID (int)
ParentNodeID (int)
UserID (int)
TS (TimeStamp)
MSG (varchar)
When viewing any node (n) all parent nodes until and including root should be selected, that is easy using the ParentNodeID pointer.
Here comes the caveat: In addition to the parent nodes all child nodes from the current node (n) should also be selected in Chronological order (based on TS) from the table. All child nodes, no matter what child-branch, that belongs to the subtree where (n) is the root.
How do I best (better) structure the table for such queries?
You should take look at how Twitter have been evolving, and check if your use case is similar enough.
A good start could be this article with database schema examples: https://web.archive.org/web/20161224194257/http://www.cubrid.org/blog/dev-platform/decomposing-twitter-database-perspective/

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

Select a field cascading

I have a categories table in MySql something like this:
categoryId | categoryTitle | definedField | parentId
1 Title 123 NULL
2 AnotherTitle 234 1
3 AndAnotherOne NULL 1
What I need to do is find the closest definedField value by going up to parent,like this;
Since category 2 has a definedField, return its value;
Since category 3 does not have a definedField, search up, to its parent. It has definedField, so return it. If it didn't have one, search up until find one.
There will ALLWAYS be the topmost category that will have definedField set. I only need to find a good algorithm to search for this in a MySQL InnoDb table.
There is no direct way of retrieving hierarchical data in MySQL (like, for example, Postgres's RECURSIVE query). There is a good article summarizing different ways of implementing nested data set in MySQL: http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
Most users at one time or another have dealt with hierarchical data in
a SQL database and no doubt learned that the management of
hierarchical data is not what a relational database is intended for.
The tables of a relational database are not hierarchical (like XML),
but are simply a flat list. Hierarchical data has a parent-child
relationship that is not naturally represented in a relational
database table.
The article covers two models: Adjacency List and Nested Set.
The Adjacency List Model
In the adjacency list model, each item in the table contains a pointer
to its parent. The topmost element, in this case electronics, has a
NULL value for its parent. The adjacency list model has the advantage
of being quite simple, it is easy to see thatFLASH is a child ofmp3
players, which is a child of portable electronics, which is a child of
electronics. While the adjacency list model can be dealt with fairly
easily in client-side code, working with the model can be more
problematic in pure SQL.
The Nested Set Model
In the Nested Set Model, we can look at our hierarchy in a new way,
not as nodes and lines, but as nested containers.

How to maintain a recursive invariant in a MySQL database?

I have a tree encoded in a MySQL database as edges:
CREATE TABLE items (
num INT,
tot INT,
PRIMARY KEY (num)
);
CREATE TABLE tree (
orig INT,
term INT
FOREIGN KEY (orig,term) REFERENCES items (num,num)
)
For each leaf in the tree, items.tot is set by someone. For interior nodes, items.tot needs to be the sum of it's children. Running the following query repeatedly would generate the desired result.
UPDATE items SET tot = (
SELECT SUM(b.tot) FROM
tree JOIN items AS b
ON tree.term = b.num
WHERE tree.orig=items.num)
WHERE EXISTS
(SELECT * FROM tree WHERE orig=items.num)
(note this actually doesn't work but that's beside the point)
Assume that the database exists and the invariant are already satisfied.
The question is:
What is the most practical way to update the DB while maintaining this requirement? Updates may move nodes around or alter the value of tot on leaf nodes. It can be assumed that leaf nodes will stay as leaf nodes, interior nodes will stay as interior nodes and the whole thing will remain as a proper tree.
Some thoughts I have had:
Full Invalidation, after any update, recompute everything (Um... No)
Set a trigger on the items table to update the parent of any row that is updated
This would be recursive (updates trigger updates, trigger updates, ...)
Doesn't work, MySQL can't update the table that kicked off the trigger
Set a trigger to schedule an update of the parent of any row that is updated
This would be iterative (get an item from the schedule, processing it schedules more items)
What kicks this off? Trust client code to get it right?
An advantage is that if the updates are ordered correctly fewer sums need to be computer. But that ordering is a complication in and of it's own.
An ideal solution would generalize to other "aggregating invariants"
FWIW I know this is "a bit overboard", but I'm doing this for fun (Fun: verb, Finding the impossible by doing it. :-)
The problem you are having is clear, recursion in SQL. You need to get the parent of the parent... of the leaf and updates it's total (either subtracting the old and adding the new, or recomputing). You need some form of identifier to see the structure of the tree, and grab all of a nodes children and a list of the parents/path to a leaf to update.
This method adds constant space (2 columns to your table --but you only need one table, else you can do a join later). I played around with a structure awhile ago that used a hierarchical format using 'left' and 'right' columns (obviously not those names), calculated by a pre-order traversal and a post-order traversal, respectively --don't worry these don't need to be recalculated every time.
I'll let you take a look at a page using this method in mysql instead of continuing this discussion in case you don't like this method as an answer. But if you like it, post/edit and I'll take some time and clarify.
I am not sure I understand correctly your question, but this could work My take on trees in SQL.
Linked post described method of storing tree in database -- PostgreSQL in that case -- but the method is clear enough, so it can be adopted easily for any database.
With this method you can easy update all the nodes depend on modified node K with about N simple SELECTs queries where N is distance of K from root node.
I hope your tree is not really deep :).
Good Luck!