Intereting Posts
Несколько внешних ключей для одиночной записи в Rails 3? SQL обновляет несколько строк по определенным идентификаторам Как я могу SELECT строк с MAX (значение столбца), DISTINCT другим столбцом в SQL? Отфильтруйте учащихся, которые еще не прошли тему Как предоставить разрешения для роли SQL для создания и управления временными таблицами ORACLE – выберите Count в подзапросе Выполнение хранимой процедуры SQL с выходным параметром из платформы Entity Framework SQL ANT TASK ERROR: класс не найден: драйвер JDBC com.microsoft.sqlserver.jdbc.SQLServerDriver не может быть загружен Как «DROP» и unamed relationship / constraints в MS Access с SQL? Как экспортировать базу данных MySQL в JSON? Создание формы, в которой пользователь вводит начальные и конечные даты отчета Как избежать двоеточия `:` внутри собственного SQL-запроса в Hibernate? SQL как строка поиска начинается с SQL-запрос для подсчета количества различных значений Использование VBA для экспорта всех запросов SQL Access в текстовые файлы

Подключить по предшествующему эквиваленту для MySQL

Все,

У меня есть три поля в таблице, которые определяют родительское дочернее отношение, существующее в базе данных MySQL версии 5.0. Имя таблицы tb_Tree и имеет следующие данные:

Table Name: tb_Tree Id | ParentId | Name -------------------- 1 | 0 | Fruits 2 | 0 | Vegetables 3 | 1 | Apple 4 | 1 | Orange 5 | 2 | Cabbage 6 | 2 | Eggplant 

Как написать запрос для получения всех детей, если указан ParentId. Обратите внимание, что приведенные данные таблицы являются только образцовыми данными, и они могут иметь гораздо больше строк. Oracle имеет предложение CONNECT BY PRIOR, но я не нашел ничего похожего на MySQL. Кто-нибудь может посоветовать?

благодаря

MySQL не поддерживает рекурсивные запросы, поэтому вам нужно сделать это сложным образом:

  1. Выберите строки, где ParentID = X где X – ваш корень.
  2. Соберите значения Id из (1).
  3. Повторите (1) для каждого Id из (2).
  4. Продолжайте рекурсию вручную, пока не найдете все листовые узлы.

Если вы знаете максимальную глубину, вы можете присоединиться к своей таблице к себе (используя LEFT OUTER JOINs) на максимально возможную глубину, а затем очистить NULL.

Вы также можете изменить представление дерева на вложенные наборы .

Вы также можете изучить этот интересный блог, который демонстрирует, как мы можем получить похожие результаты в mysql

http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

Это старая нить, но, поскольку у меня возник вопрос на другом форуме, я подумал, что добавлю его здесь. В этом случае я создал хранимую процедуру, жестко закодированную для обработки конкретного случая. Это, конечно, имеет некоторые недостатки, поскольку не все пользователи могут создавать хранимые процедуры по своему усмотрению, но тем не менее.

Рассмотрим следующую таблицу с узлами и дочерними элементами:

 CREATE TABLE nodes ( parent INT, child INT ); INSERT INTO nodes VALUES ( 5, 2), ( 5, 3), (18, 11), (18, 7), (17, 9), (17, 8), (26, 13), (26, 1), (26,12), (15, 10), (15, 5), (38, 15), (38, 17), (38, 6), (NULL, 38), (NULL, 26), (NULL, 18); 

В этой таблице следующая хранимая процедура будет вычислять результирующий набор, состоящий из всех декадентов предоставленного узла:

 delimiter $$ CREATE PROCEDURE find_parts(seed INT) BEGIN -- Temporary storage DROP TABLE IF EXISTS _result; CREATE TEMPORARY TABLE _result (node INT PRIMARY KEY); -- Seeding INSERT INTO _result VALUES (seed); -- Iteration DROP TABLE IF EXISTS _tmp; CREATE TEMPORARY TABLE _tmp LIKE _result; REPEAT TRUNCATE TABLE _tmp; INSERT INTO _tmp SELECT child AS node FROM _result JOIN nodes ON node = parent; INSERT IGNORE INTO _result SELECT node FROM _tmp; UNTIL ROW_COUNT() = 0 END REPEAT; DROP TABLE _tmp; SELECT * FROM _result; END $$ delimiter ; 

В приведенном ниже списке перечислены все растения и их parentid до 4-х уровневых (и, конечно, вы можете расширить уровень):

 select id, name, parentid ,(select parentid from tb_tree where id=t.parentid) parentid2 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid)) parentid3 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid))) parentid4 from tb_tree t 

и затем вы можете использовать этот запрос для получения окончательного результата. например, вы можете получить всех детей из «Фруктов» по ​​следующим sql:

 select id ,name from ( select id, name, parentid ,(select parentid from tb_tree where id=t.parentid) parentid2 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid)) parentid3 ,(select parentid from tb_tree where id=(select parentid from tb_tree where id=(select parentid from tb_tree where id=t.parentid))) parentid4 from tb_tree t) tt where ifnull(parentid4,0)=1 or ifnull(parentid3,0)=1 or ifnull(parentid2,0)=1 or ifnull(parentid,0)=1 

Следующая хранимая процедура упорядочивает таблицу, в которой есть строки с обратной ссылкой на предыдущую. Обратите внимание, что на первом этапе я копирую строки в таблицу temp – эти строки соответствуют некоторому условию. В моем случае это строки, которые принадлежат к той же линейной (дорога, которая используется в GPS-навигации). Бизнес-домен не важен. Как раз в моем случае я сортирую сегменты, принадлежащие к той же дороге

ПРОЦЕДУРА УБЫТКОВ, ЕСЛИ СУЩЕСТВУЕТ, orderLocations; DELIMITER //

CREATE PROCEDURE orderLocations (_full_linear_code VARCHAR (11)) НАЧАТЬ

 DECLARE _code VARCHAR(11); DECLARE _id INT(4); DECLARE _count INT(4); DECLARE _pos INT(4); DROP TEMPORARY TABLE IF EXISTS temp_sort; CREATE TEMPORARY TABLE temp_sort ( id INT(4) PRIMARY KEY, pos INT(4), code VARCHAR(11), prev_code VARCHAR(11) ); -- copy all records to sort into temp table - this way sorting would go all in memory INSERT INTO temp_sort SELECT id, -- this is primary key of original table NULL, -- this is position that still to be calculated full_tmc_code, -- this is a column that references sorted by negative_offset -- this is a reference to the previous record (will be blank for the first) FROM tmc_file_location WHERE linear_full_tmc_code = _full_linear_code; -- this is how many records we have to sort / update position SELECT count(*) FROM temp_sort INTO _count; -- first position index SET _pos = 1; -- pick first record that has no prior record SELECT code, id FROM temp_sort l WHERE prev_code IS NULL INTO _code, _id; -- update position of the first record UPDATE temp_sort SET pos = _pos WHERE id = _id; -- all other go by chain link WHILE (_pos < _count) DO SET _pos = _pos +1; SELECT code, id FROM temp_sort WHERE prev_code = _code INTO _code, _id; UPDATE temp_sort SET pos = _pos WHERE id = _id; END WHILE; -- join two tables and return position along with all other fields SELECT t.pos, l.* FROM tmc_file_location l, temp_sort t WHERE t.id = l.id ORDER BY t.pos; END;