entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

¿Cómo ordenar números consecutivos decimales en mysql?

Necesito ordenar unos registros, de mi tabla menusecuencia, en donde los datos que tengo son:

Id Menu
1.10 1
1.11 1
2.10 2
2.11 2
2.12 2
3.10 3
3.11 3

La cuestión es que si elimino el registro "2.11 2", la tabla quedaria:
Id Menu
1.10 1
1.11 1
2.10 2
2.12 2
3.10 3
3.11 3

o bien si elimino los campos donde Menu=2
Id Menu
1.10 1
1.11 1
3.10 3
3.11 3

Como puedo ordenar los valores es decir los 3 pasarían a ser 2? AYUDAAAAAA!!!

0voto

Leonardo-Tadei comentado

No entiendo del todo tu pregunta: consultás sobre cómo ordenar pero nos mostrás los datos ordenados, como si lo hubieras hecho.

Agregá a la pregunta la estructura de la tabla y la query que estás planteando que no te funciona... o al menos los datos desordenados desde los que partís.

0voto

cind10 comentado

Mi tabla original
enter link description here
Mi tabla cuando elimino registro
enter link description here

Ahora bien los tres deben pasar a ser 2 eso es lo que intento hacer.

0voto

ctapiamori comentado

@Leonardo-Tadei, creo que @cind10 desea actualizar los numeros de los menus, que estos sean consecutivos, si borro uno del medio los que estan delante de el deberian actualizarce nuevamente de forma consecutiva, por eso indica si elimina los de menu=2, entonces los del menu=3 deberian iniciar con el 2, eso pudo entenderlo, pero bueno @cin10 indicanos si es asi?

0voto

cind10 comentado

Exacto!!!!! eso es lo que busco @ctapiamori

0voto

Leonardo-Tadei comentado

Gracias @ctapiamori por la explicación y por ampliar lo que dice la pregunta! ahora la entiendo...

3 Respuestas

0voto

Leonardo-Tadei Puntos227320

Tu tabla viola la Primera Forma Normal, ya que tiene más de un fvalor en un campo.
Cuando el almacenamiento no está Normalizado, hay querys que son imposibles de hacer.

Si tu tabla está bien Normalizada, la query a ejecutar consistiría en restar 1 a todos loe elementos del menú que tengan un submenu mayor que el elemento que borraste... al tener dos datos en el mismo campo, la query se puede hacer en este caso particular, pero es ineficiente y extremadamente compleja en relación a datos bien almacenados :-(

0voto

ctapiamori comentado

No lo veo facil, entendiendo sus ejemplos:
1) ejemplo se elimina un registro
1.11 1; 2.10 2; 2.12 2;3.10 3
para resolverlo deberia quedar
1.11 1; 2.10 2; 2.11 2;3.10 3

En este caos no elimina 1, elimina 0.01, ademas no sabe si elimino un menu por completo, solo sabe que se elimino un registro.

2) ejemplo se elemina los registros con menu=2
1.10 1; 1.11 1; 3.10 3;3.11 3
para resolverlo deberia quedar
1.10 1; 1.11 1; 2.10 2;2.11 2

Si te percatas hubo cambio de menu y de identificador, y tampoco seria quitando un valor.

Veo complejo realizar un cambio asi, lo unico que podria recomendarte es que recuperes todos registros superiores al registro que estas eliminando, y realices las verificaciones de valores y vuelvas a recalcular los números, pero lo veo muy tedioso, te preguntaría @cind10 cual es el motivo de realizar esto?

0voto

cind10 comentado

Pretendo realizar un sistema de permisos en donde el menu se maneje MENU PRINCIPAL Y SUBMENU asi:
Usuario X tiene acceso a las opciones:
MENU PRINCIPAL OPCION 1:
SUBMENU 1.1
SUBMENU 1.2
SUBMENU 1.3

MENU PRINCIPAL OPCION 2:
SUBMENU 2.1
SUBMENU 2.2
SUBMENU 2.3

...... ETC....

seria muy complicado?? me gustaría me diera su punto de vista @ctapiamori. gracias

0voto

Leonardo-Tadei comentado

Para una tabla normalizada que represente un árbol como esta:

id  numeric not null,  -- el identificador de la tabla
self_key_id numeric,   -- el identificador a si misma
data varchar(25) );    -- la info. que se va a almacenar (se pueden agregar más campos si el problema lo requiere.

esta sola query te devuleve el árbol completo, sin necesidad de pasar todos los datos a un vector para procesarlos y sin necesidad de ejecutar una query para cada nivel:

SELECT a.id, a.data, b.self_key_id AS pid, b.data as data_node
  FROM self_key_table AS a
  LEFT JOIN self_key_table AS b
            ON a.id = b.self_key_id
 ORDER BY a.id, a.data, b.data

Esto se llama "modelo de adyasencia" y es la forma más óptima de representar y acceder a un árbol almacenado en una tabla.

La única consideración a tener es que el registro que represente a la raíz, deber ener el valor de self_key=null

En el ejemplo el único dato del arbol es el campo "data", pero se pueden agregar todos los campos que te hagan falta para tu problema.

En este artículo se explica el proceso con más detalle http://www.sitepoint.com/hierarchical-data-database/

Saludos cordiales!

0voto

ctapiamori Puntos1050

Te recomiendo agregar un campo ORDEN a tu tabla de MENU y SUBMENU, no te preocupes si los identificadores (1, 2, 3, ..) no son consecutivos, por que son datos internos que sirven como identificación de un registro, pero si necesitas mostrar ordenado tus opciones, entonces con un campo ORDEN te falicitara hacerlo, ahora no te preocupes si hay valores que no sean consecutivo, lo que debe importarte es como se muestra en pantalla.

0voto

Leonardo-Tadei comentado

Si normalizara bien la tabla, el campo "orden" no haría falta... no es que tu solución o sea buena, es que serguirán mal los almaceamientos :-(

0voto

ctapiamori comentado

Pienso que es una solución práctica, si fuera normalizado, lo que implicaría cambiar la estructura y forma de trabajo actual, entonces estamos hablando de un cambio grande, y en ese caso yo veo que seria mejor agregar solo un campo ORDEN, no veo que tenga una gran importancia que los identificadores sean consecutivos, por que no hay un proceso que lo use, entonces estos pueden variar sin afectar la necesidad que se tiene de ellos, creo que también debemos considerar todo eso.

0voto

Leonardo-Tadei comentado

Te entiendo, de veras, y sé que sueno a viejo cascarrabias, pero la verdadera solución es normalizar... lo demás, con todo cariño y respeto hacia tu opinión, es querer salvar algo que no debió de haber existido. Luego veremos como surge un nuevo problema, como que por ejemplo los datos deben repetirse por cada usuario o cada perdil de usuario que tiene acceso :-(

Además, según nos cuenta ahora @cind10, esta estructura de menú es para limitar el acceso a partes de una aplicación, como si limitando el menú solamente no se pudiera acceder a las cosas más o menos fácilmente. Es muy posible que los números no tengan que ser consecutivos y que puedan ser completamente arbitrarios para manejar el acceso.

Saludos cordiales!

1voto

white Puntos75880

Antes de buscar una solucion como lo que pides, es mejor hacer lo que te indica @Leonardo, pon a tus tablas en segunda forma normal eliminando las dependencias parciales o puedes dar una mejor estructura a tu tabla, por ejemplo crear una columna que almacene el id del menu padre, si es 0 entonces es un menu padre.

la estructura podría ser:

+------------+------------+------+-----+---------+----------------+
| Field      | Type       | Null | Key | Default | Extra          |
+------------+------------+------+-----+---------+----------------+
| id         | int(11)    | NO   | PRI | NULL    | auto_increment |
| parent_id  | int(11)    | NO   |     | 0       |                |
| menu_order | int(11)    | NO   |     | NULL    |                |
| permission | tinyint(2) | NO   |     | NULL    |                |
+------------+------------+------+-----+---------+----------------+

+----+-----------+------------+------------+
| id | parent_id | menu_order | permission |
+----+-----------+------------+------------+
|  1 |         0 |          1 |          2 |
|  2 |         1 |          2 |          1 |
|  4 |         1 |          3 |          3 |
|  5 |         0 |          1 |          4 |
|  6 |         5 |          2 |          5 |
|  7 |         5 |          3 |          3 |
|  8 |         0 |          1 |          5 |
|  9 |         8 |          2 |          5 |
+----+-----------+------------+------------+

de esta forma podrias hacer menus multi nivel.

para recuperar los datos, dependiendo los niveles del menu, podrias usar recursividad. en php seria algo asi:

<?php

$result = $mysqli->query(
    'SELECT *
     FROM menus
     ORDER BY menu_order ASC');

$menus = array(
    'parents' => array()
);

while($row = $result->fetch_assoc())
{
    if($row['parent_id'] == 0)
    {
        $parent_pos = count($menus['parents']) + 1;

        $menus['parents'][$row['id']] = array(
            'position' => $parent_pos,
            'parent' => $row,
            'childrens' => array()
        );

        continue;
    }

    $actual_childrens = $menus['parents'][$row['parent_id']]['childrens'];
    $row += array('position' => count($actual_childrens) + 1);
    $menus['parents'][$row['parent_id']]['childrens'][] = $row;
}

foreach($menus['parents'] as $key => $parent)
{
    echo '<div class="menu">' . sprintf('<strong>menu #%d</strong><ul>', $parent['position']);

    foreach ($parent['childrens'] as $child) {
        echo sprintf('<li>sub menu #%d.%d</li>', $parent['position'], $child['position']);
    }

    echo '</ul></div>';
}

menu #1

  • sub menu #1.1
  • sub menu #1.2

menu #2

  • sub menu #2.1
  • sub menu #2.2

menu #3

  • sub menu #3.1

saludos!

0voto

cind10 comentado

Agradezco mucho sus comentarios @Leonardo-Tadei , @ctapiamori, @white

0voto

Leonardo-Tadei comentado

Hola @white !

en mi respuesta de arriba pongo un ejemplo de tabla para mapear un árbol usando el modelo de adyacencia, que con una sola query devuelve el árbol completo y ordenado.

Esto evita tener que cargar la tabla entera a un vector para procesarla y obtener el árbol armado.

Saludos cordiales!

0voto

white comentado

Muy de acuerdo con tu respuesta @Leonardo, A no ser que se requiera reconstruir la jerarquia . me voy mas por lo jerárquico que lo relacional.

saludos!

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta