Sorting data from one column to another

Asked

Viewed 174 times

2

I am setting up a hierarchy and everything is working correctly, I just have a small problem, in the ordering of the data.

Follows the structure of the table. (as basic as possible)

create table hierarquia (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `hierarquia_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
);

and the data are these:

insert into hierarquia values
(1, 0), 
(2, 0), 
(3, 1), 
(4, 1),
(5, 0),
(6, 3);

When I do my query select * from hierarquia order by hierarquia_id, id does not return the data in the order I need.

ID | HIERARQUIA_ID
1  | 0
2  | 0 
5  | 0
3  | 1 
4  | 1
6  | 3

It would need to return the data more consistently ordered by their hierarchies, and it would have to return the data like this:

ID | HIERARQUIA_ID
1  | 0
3  | 1 
6  | 3
4  | 1
2  | 0 
5  | 0

First the first hierarchy without sub-hierarchy, the next being the sub-hierarchy of the first and consecutively.

There is this possibility in the ?

Example in Sqlfiddle

  • 2

    Man, relational databases are no good with tree structures like yours. You want to return the list of tree nodes when traversed in pre-order. Mysql is pretty spartan for handling spatial data.

  • @Henriquebarcelos the bank itself runs well, my only problem even though it is in this ordination. I even understand what you mean, but I’m trying, because unfortunately I have no way to change this structure, very much to a noSql, at least not now. But Valew for the return.

  • 1

    So there is no direct way to do this. The best way to do it is by using the programming language in the application that accesses this data.

  • There are some "technical adjustments" that you find here and that can give a light to you solve your problem.

  • I’ll take a look, and as I said, I might do it on the schedule anyway. Valew

1 answer

2

Solution using stored Procedure

I found in SOEN, a solution based on stored Procedure, which does not require changing the structure of the bank:

https://stackoverflow.com/a/11035966/195417

Solution changing the seat structure

I once worked with this problem of sorting the records in the same order they appear in the tree, and the final solution was to create a new column in the database, with the address of each record inside the tree, in the form of the same string:

ID | HIERARQUIA_ID | ENDERECO
1  | 0             | "1"
2  | 0             | "2"
3  | 1             | "1\3"
4  | 1             | "1\4"
5  | 0             | "5"
6  | 3             | "1\3\6"

After sorting by the address column, would be in the order you want:

ID | HIERARQUIA_ID | ENDERECO
1  | 0             | "1"
3  | 1             | "1\3"
6  | 3             | "1\3\6"
4  | 1             | "1\4"
2  | 0             | "2"
5  | 0             | "5"

Sqlfiddle

  • I had not thought about this possibility, I understood and I thought it was cool, but for this I need to change my structure and I will also have to work on the programming that saves this data in the database (something that for this moment I will not have time) but it is the tip reported here.

  • The construction of the address and even the list of ordered adjacency can be done via stored procedures; although I agree with Henrique that this is better and more performative in the application layer. See this question in DBA Exchange. The address value can be calculated with a function analogous to GetAncestry that concatenates the nodes in preorder.

  • 2

    Proof of concept using Miguel’s suggestion + adaptation of the mentioned function (does not require a new column in the bank). It works, but these concatenations and the fact that each relative of a node means one SELECT makes this solution very problematic in terms of performance.

  • @Anthonyaccioly: this DBA Exchange response is conicidentely the same as I found, but linked from within a response on SOEN. = D

  • @Anthonyaccioly: by the way, your proof of concept was great. Thanks! The only problem would be the performance.

  • @Marcelodiniz: Dude, now it’s not a matter of time... you can just create the column ENDERECO and then use the stored UPDATE to update the entire bank with the correct values. So you have performance, and at the same time solve the problem quickly... unless there are other issues involved.

  • Long live the Rolandomysqldba proposed (and replicated the solution). If you want to copy or adapt the POC and include it in the answer, feel free :).

  • Guys, really good, I thank you all and I will analyze what best to do. @Anthonyaccioly your proof of concept turned out really good, but there is the issue of performance that can harm. I thank you all very much.

  • Marcelo, as suggested by Miguel you can create an address column (properly indexed) and use my function to feed it (a update initial in the whole table and maybe some triggers clever on insert and on update propagating modifications tree below). This is a more performative solution (exchanging calculations at each reading for pre-indexed calculations during writing operations). Better than that just bringing the problem to a programming language able to handle graphs / even hierarchical data structures.

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.