Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Drzewka w MySQL sortowanie, metoda ip
Forum PHP.pl > Forum > Bazy danych > MySQL
eai
Stworzyłem swój system drzewek za pomocą metody "IP".
Polega na tym że w TREE znajduje się mapa zagnieżdzenia (id rodzielone kropką).
Dodatkowo stosuje dopełnianie zerami, w celu utrzymania kolejności zagnieżdzenia (prawidłowe sortowanie liczb, które są łańcuchem znaków a nie typem INT). 10 cyfrowa liczba ponieważ ID (INTEGER) może mieć największą wartość równą 4 294 967 295.

Przy polu tree o długości 255 znaków możliwe jest utworzenie 23 poziomów.
Jeśli pole będzie typu TEXT będzie napewno o wiele więcej.

Tabela:
Kod
+-----------+-------------------+------+-----+------------+----------------+
| Field     | Type              | Null | Key | Default    | Extra          |
+-----------+-------------------+------+-----+------------+----------------+
| id        | int(10) unsigned  | NO   | PRI | NULL       | auto_increment |
| parent_id | int(10)           | NO   |     | 0          |                |
| tree      | varchar(255)      | NO   |     | 0000000000 |                |
| depth     | int(100) unsigned | NO   |     | 0          |                |
| name      | varchar(255)      | NO   |     | NULL       |                |
| position  | int(10) unsigned  | NO   |     | 0          |                |
+-----------+-------------------+------+-----+------------+----------------+
6 rows in set (0,00 sec)


Tworzymy tabelę
  1. CREATE TABLE `drzewko` (
  2. `id` INT( 10 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
  3. `parent_id` INT( 10 ) NOT NULL DEFAULT '0',
  4. `tree` VARCHAR( 255 ) NOT NULL DEFAULT '0000000000',
  5. `depth` INT( 100 ) UNSIGNED NOT NULL DEFAULT '0',
  6. `name` VARCHAR( 255 ) NOT NULL ,
  7. `position` INT( 10 ) UNSIGNED NOT NULL DEFAULT '0'
  8. ) ENGINE = MYISAM;


Dodajemy dane
  1. INSERT INTO `drzewko` (`id`, `parent_id`, `tree`, `depth`, `name`, `position`) VALUES
  2. (1, 0, '0000000000', 0, 'Tomek', 2),
  3. (2, 0, '0000000000', 0, 'Jacek', 1),
  4. (3, 2, '0000000000.0000000002', 1, 'Placek', 2),
  5. (4, 2, '0000000000.0000000002', 1, 'Gacek', 3),
  6. (5, 2, '0000000000.0000000002', 1, 'Kowalski', 1),
  7. (6, 5, '0000000000.0000000002.0000000005', 2, 'Nowak', 1),
  8. (7, 1, '0000000000.0000000001', 1, 'Pod kategoria', 0);


Wyświetlenie drzewka:
  1. SELECT * FROM `drzewko` ORDER BY CONCAT(tree,'.', LPAD(id,10,0))


Wynik:
Kod
+----+-----------+----------------------------------+-------+---------------+----------+
| id | parent_id | tree                             | depth | name          | position |
+----+-----------+----------------------------------+-------+---------------+----------+
|  1 |         0 | 0000000000                       |     0 | Tomek         |        2 |
|  7 |         1 | 0000000000.0000000001            |     1 | Pod kategoria |        0 |
|  2 |         0 | 0000000000                       |     0 | Jacek         |        1 |
|  3 |         2 | 0000000000.0000000002            |     1 | Placek        |        2 |
|  4 |         2 | 0000000000.0000000002            |     1 | Gacek         |        3 |
|  5 |         2 | 0000000000.0000000002            |     1 | Kowalski      |        1 |
|  6 |         5 | 0000000000.0000000002.0000000005 |     2 | Nowak         |        1 |
+----+-----------+----------------------------------+-------+---------------+----------+

Wszystko ładnie się wyświetla w odpowiednim porządku, ponieważ stosuje dopełnianie z lewej strony zerami.

Ale to czego potrzebuje to posortować te wyniki dodatkowo według pozycji (position).
Na tym etapie trzeba wprowadzić warunek: sortowane mają być wiersze według pola position które mają taki sam parent_id.
Czyli najpierw sortowane są względem struktury drzewiastej a teraz tam gdzie parent_id jest wspólny chce dodatkowo posortować według pola position.

Napewno trzeb będzie zrobić SELECTA z SELECTA, ale nie wiem jak do tego postawić warunek że mają się sortować według pola position tylko te pola które mają ten sam parent_id.

  1. SELECT * FROM (SELECT * FROM `drzewko` ORDER BY CONCAT(tree,'.', LPAD(id,10,0))) ORDER BY position ...?


Ewentualnie w jaki sposób napisać do tego procedurę która te dane posortuje?


EDIT
Po przeprowadzaniu wielokrotnych testów nie udało mi się tym sposobem znaleźć rozwiązania.
Podaje linki do lepszego rozwiązania problemu struktury drzewiastej

http://www.eioba.pl/a130/drzewa_w_php_i_mysql
http://www.artfulsoftware.com/mysqlbook/sa...sqled1ch20.html
tomek_
A nie wystarczy 

  1. SELECT * FROM `drzewko` ORDER BY CONCAT(tree,'.', LPAD(id,10,0)), position;




swoją drogą nie wiem po co Ci pole tree - skoro masz parent_id to wystarczy żeby wyciągnąć potrzebe Ci dane 
eai
Założenia są takie:
- bez rekursywności
- zwrócone dane mają być posortowane według:
a) struktry drzewa (rodzic, dziecko)
cool.gif posortowane wewnątrz swojej gałęzi

O to kilka przykładów wyników:
Posortowane według struktry drzewa (rodzic, dziecko)
  1. SELECT CONCAT(REPEAT(' ', depth), name) AS name FROM `drzewko` ORDER BY CONCAT(tree,'.', LPAD(id,10,0));

Kod
+-----------------+
| name            |
+-----------------+
| Tomek           |
|   Pod kategoria |
| Jacek           |
|   Placek        |
|   Gacek         |
|   Kowalski      |
|     Nowak       |
+-----------------+
7 rows in set (0,00 sec)

Wszystko jest ok poza tym że nie są dodatkowo posortowane według pozycji (pole position)

Propozycja tomka
  1. SELECT CONCAT(REPEAT(' ', depth), name) AS name, position FROM `drzewko` ORDER BY CONCAT(tree,'.', LPAD(id,10,0)), position;

Kod
+-------------------+----------+
| name              | position |
+-------------------+----------+
| Tomek             |        2 |
|     Pod kategoria |        0 |
| Jacek             |        1 |
|     Placek        |       55 |
|     Gacek         |       45 |
|     Kowalski      |      180 |
|         Nowak     |        1 |
+-------------------+----------+
7 rows in set (0,00 sec)

Jak widać nie przynosi to pożądanego efektu.

Propozycja mojego kolegi
  1. SELECT CONCAT(REPEAT(' ', depth), name) AS name, position FROM `drzewko` ORDER BY tree, position;

Kod
+-------------------+----------+
| name              | position |
+-------------------+----------+
| Jacek             |        1 |
| Tomek             |        2 |
|     Pod kategoria |        0 |
|     Gacek         |       45 |
|     Placek        |       55 |
|     Kowalski      |      180 |
|         Nowak     |        1 |
+-------------------+----------+
7 rows in set (0,00 sec)

Jak widać wszystko się rozsypało.

Druga propozycja tego samego kolegi
  1. SELECT CONCAT(REPEAT(' ', depth), name) AS name, position FROM `drzewko` ORDER BY CONCAT(tree,'.', LPAD(position,10,0))

Kod
+-------------------+----------+
| name              | position |
+-------------------+----------+
| Jacek             |        1 |
|     Pod kategoria |        0 |
| Tomek             |        2 |
|         Nowak     |        1 |
|     Gacek         |       45 |
|     Placek        |       55 |
|     Kowalski      |      180 |
+-------------------+----------+
7 rows in set (0,00 sec)

Jak widać również nieskuteczna.


Padło pytanie dlaczego dopełniam zerami tree?
Ponieważ jest typu VARCHAR czyli string, a to znaczy że nie jest liczbą i sortowanie przynosi zupełnie inny efekt.

Pole typu INT posortuje liczby 1,11,2,21,33 w kolejności 1,2,11,21,33 natomiast pole typu VARCHAR te same liczby posortuje w kolejności 1,11,2,21,33 co jest logiczne bo traktuje je jako łańcuch znaków a nie liczbę.

Mam nadzieję że troche wam wyjaśniłem. Próbuje napisać do tego procedurę która będzie mi tylko sortowała wyniki z mojego pierwszego zapytania. Ale jak narazie bezskutecznie.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.