Ако това е всичко, от което се нуждаете, можете да използвате търсене с LIKE
SELECT *FROM Table1WHERE CELL LIKE 'AEE%';
С индекс, започващ с CELL
това е проверка на диапазон, която е бърза.
Ако вашите данни не изглеждат така, можете да създадете path
колона, която изглежда като път на директория и съдържа всички възли "по пътя/пътя" от корена до елемента.
За да извлечете всички наследници на „AE“ (включително себе си), вашата заявка ще бъде
SELECT *FROM дърво tWHERE път КАТО '1/6/%';
или (специфично за MySQL конкатенация)
SELECT t.*FROM дърво tCROSS JOIN дърво r -- rootWHERE r.CELL ='AE' И t.path LIKE CONCAT(r.path, '%');
Резултат:
<предварителен код>| ID | КЛЕТКА | parent_id | път ||====|======|===========|==========|| 6 | AE | 1 | 1/6/ || 7 | AEA | 6 | 1/6/7/ || 8 | AEE | 6 | 1/6/8/ || 9 | AEEB | 8 | 1/6/8/9/ |Ефективност
Създадох 100 хиляди реда с фалшиви данни в MariaDB с плъгин за последователност използвайки следния скрипт:
изтрийте таблица, ако съществува дърво; CREATE TABLE дърво ( `id` int първичен ключ, `CELL` varchar(50), `parent_id` int, `path` varchar(255), уникален индекс (`CELL` ), уникален индекс (`path`)); ПУСКАНЕ НА ЗАПУСКАНЕ, АКО СЪЩЕСТВУВА `tree_after_insert`; РАЗДЕЛИТЕЛ //СЪЗДАВАНЕ НА ЗАПУСКАНЕ `tree_after_insert` ПРЕДИ ВМЪКВАНЕ НА `дърво` ЗА ВСЕКИ РЕД НАЧАЛО ако new.id =1 след това задайте new.path :='1/'; else set new.path :=concat(( изберете път от дърво, където id =new.parent_id), new.id, '/'); end if;END//DELIMITER;вмъкване в дърво изберете seq като id, conv(seq, 10, 36) като CELL, случай когато seq =1 тогава null else floor(rand(1) * (seq-1)) + 1 край като parent_id, null като път от seq_1_to_100000; ОТПУСКАНЕ НА ЗАПУСКАНЕ, АКО СЪЩЕСТВУВА `tree_after_insert`;-- време на изпълнение ~ 4 сек.
Тестове
Пребройте всички елементи под корена:
SELECT count(*)FROM дърво tCROSS JOIN дърво r -- rootWHERE r.CELL ='1' И t.path LIKE CONCAT(r.path, '%');-- резултат:100000-- време на работа:~ 30 ms
Вземете елементи на поддърво под конкретен възел:
SELECT t.*FROM дърво tCROSS JOIN дърво r -- rootWHERE r.CELL ='3B0' И t.path LIKE CONCAT(r.path, '%');-- време на изпълнение:~ 30 msкод>
Резултат:
<предварителен код>| ID | КЛЕТКА | parent_id | път ||=======|======|===========|======================================|| 4284 | 3B0 | 614 | 1/4/11/14/614/4284/ || 6560 | 528 | 4284 | 1/4/11/14/614/4284/6560/ || 8054 | 67Q | 6560 | 1/4/11/14/614/4284/6560/8054/ || 14358 | B2U | 6560 | 1/4/11/14/614/4284/6560/14358/ || 51911 | 141Z | 4284 | 1/4/11/14/614/4284/51911/ || 55695 | 16Z3 | 4284 | 1/4/11/14/614/4284/55695/ || 80172 | 1PV0 | 8054 | 1/4/11/14/614/4284/6560/8054/80172/ || 87101 | 1V7H | 51911 | 1/4/11/14/614/4284/51911/87101/ |PostgreSQL
Това също работи за PostgreSQL. Трябва да се промени само синтаксисът за конкатенация на низове:
SELECT t.*FROM дърво tCROSS JOIN дърво r -- rootWHERE r.CELL ='AE' И t.path LIKE r.path || '%';
Как работи търсенето
Ако погледнете тестовия пример, ще видите, че всички пътища в резултата започват с '1/4/11/14/614/4284/'. Това е пътят на корена на поддървото с CELL='3B0'
. Ако пътят
колоната е индексирана, машината ще ги намери всички ефективно, тъй като индексът е сортиран по path
. Все едно бихте искали да намерите всички думи, които започват с „pol“ в речник със 100K думи. Няма нужда да четете целия речник.