Выборка элементов 3 уровня в иерархии MySQL

354
05 марта 2017, 06:58
CREATE TABLE `folder_s` (
`folder_id` int(10) NOT NULL AUTO_INCREMENT,
`folder_name` varchar(10) DEFAULT NULL,
`folder_type` varchar(10) DEFAULT NULL,
`creation_date` varchar(20) DEFAULT NULL,
`author` varchar(20) DEFAULT NULL,
`parent_id` int(11) NOT NULL,
PRIMARY KEY (`folder_id`),
KEY `bbbb_idx` (`parent_id`),
CONSTRAINT `FKparent_folder` FOREIGN KEY (`parent_id`) REFERENCES `folder_s` (`folder_id`) ON DELETE CASCADE ON UPDATE CASCADE
CREATE TABLE `document_s` (
`document_id` int(10) NOT NULL AUTO_INCREMENT,
`document_name` varchar(20) DEFAULT NULL,
`document_type` varchar(20) DEFAULT NULL,
`creation_date` varchar(20) DEFAULT NULL,
`parent_id` int(10) DEFAULT NULL,
PRIMARY KEY (`document_id`),
KEY `aaa` (`parent_id`),
CONSTRAINT `aaa` FOREIGN KEY (`parent_id`) REFERENCES `folder_s` (`folder_id`) ON DELETE CASCADE ON UPDATE NO ACTION

Элементы Folder_s являются папками в которых могут содержаться как другие папки, так и документы из document_s.

Таким образом если у меня есть данные например

INSERT INTO `folder_s` VALUES 
(1,'/','/','2017/02/21','admin',1),
(2,'root','root','2017/02/21','admin',1),
(3,'Folder A','Dosar','2017/02/26 23:27','nolek',2),
(4,'Folder B','Catalog','2017/02/26 23:27','nolek',2),
(5,'Folder C','Pachet','2017/02/26 23:27','nolek',3),
(6,'Folder D','Dosar','2017/02/26 23:28','nolek',4);
(7,'Folder E','Dosar','2017/02/26 23:28','nolek',5);
(8,'Folder F','Dosar','2017/02/26 23:28','nolek',6);

INSERT INTO `document_s` VALUES 
('1', 'DocumentA', 'Dosar', '2017/02/26 23:27', '2'),
('2', 'DocumentB', 'DocExt', '2017/02/26 23:27', '2'),
('3', 'DocumentC', 'Dosar', '2017/02/26 23:27', '5'),
('4', 'DocumentD', 'DocExt', '2017/02/26 23:27', '5'),
('5', 'DocumentE', 'Dosar', '2017/02/26 23:27', '6'),
('6', 'DocumentF', 'DocExt', '2017/02/26 23:27', '6'),
('7', 'DocumentG', 'Dosar', '2017/02/26 23:27', '7'),
('8', 'DocumentH', 'DocInt', '2017/02/26 23:27', '8');

всё что находится в руте это нулевой уровень И необходимо сделать выборку документов 3-го уровня то есть

Root
    FolderA
           FolderC
                  FolderE
                            DocumentG
                  DocumentC
                  DocumentD
    FolderB
           FolderD
                  FolderF
                         DocumentH
                  DocumentE
                  DocumentF
    DocumentA
    DocumentB

В таком дереве это будет

DocumentC
DocumentD
DocumentE
DocumentF

Подскажите как это можно осуществить в MySQL и каким образом вообще это осуществить.

Answer 1

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

select *
  from (
        select @grp:=(select group_concat(folder_id)
                        from folder_s
                       where find_in_set(parent_id,@grp)>0 and folder_id!=parent_id
               ) grp,
               @level:=@level+1 level
          from folder_s, (select @grp:='1',@level:=0) X
         limit 3
      ) A
  join document_s
    on A.level=3 and find_in_set(parent_id,grp)>0

В связи с использованием find_in_set при выполнении потребуется 3 полных сканирований таблицы folder и одно полное сканирование таблицы documents.

Работает достаточно просто, получаем N строк из любой таблицы (в данном случае из самой же folder), ограничивая это количество limit. На каждой строке подзапросом получаем список дочерних id для всех родителей id которых есть в списке в переменной @grp, полученный в предыдущей строке. Таким образом эмулируем цикл по уровням.

Для более быстрой работы можно сделать хранимую процедуру, которая реализует настоящий цикл и на каждом уровне получает тот же список дочерних папок но не в виде строки, а построчно сохраняя во временную таблицу.

В принципе, если уровень фиксированно 3й, можно конечно решить задачу обычным образом:

select D.*
  from folder_s L1,
       folder_s L2,
       folder_s L3,
       document_s D
 where L1.parent_id=1 and L1.folder_id!=L1.parent_id
   and L2.parent_id=L1.folder_id
   and L3.parent_id=L2.folder_id
   and D.parent_id=L3.folder_id
READ ALSO
Ant-сборка проекта в Eclipse с подключением .dll

Ant-сборка проекта в Eclipse с подключением .dll

Я пишу игру на Java с использованием 2D движка Slick2DВ Eclipse IDE проект работает штатно, а при сборке и запуске через File>Export в Runnable JAR File дальше главного...

281
Ошибка при отправке Email

Ошибка при отправке Email

Подскажите почему не отправляет е-мейлпрограмма запускается и не выдает ексепшены и не заканчивается

283