MySQL - пока существует из фрагмента кода ошибка - PullRequest
0 голосов
/ 08 февраля 2019

Я читал эту страницу https://www.sqlteam.com/articles/more-trees-hierarchies-in-sql (отличная статья об управлении иерархическими данными в SQL) и следовал в MySQL и пытался запустить этот фрагмент SQL.

WHILE EXISTS (SELECT * FROM Tree WHERE Depth Is Null) 
UPDATE T SET T.depth = P.Depth + 1, 
T.Lineage = P.Lineage + Ltrim(Str(T.ParentNode,6,0)) + '/' 
FROM Tree AS T 
INNER JOIN Tree AS P ON (T.ParentNode=P.Node) 
WHERE P.Depth>=0 
AND P.Lineage Is Not Null 
AND T.Depth Is Null

Кроме Iполучите следующую ошибку:

У вас есть ошибка в вашем синтаксисе SQL;кажется, что ошибка заключается в следующем: 'WHILE EXISTS (SELECT * FROM Tree, Глубина равна нулю) UPDATE' в строке 1

Я пытался добавить BEGIN, END, END WHILE и т.д. из предложений в Хотя существует в mysql , но все еще не работает.

Вы можете попробовать запустить приведенный выше фрагмент в валидаторе SQL (https://www.eversql.com/sql-syntax-check-validator/ - хороший бесплатный онлайн1) и вижу ошибку.

Я ищу предложения о том, почему вышеприведенный фрагмент не работает из блога / что можно изменить, чтобы получить тот же результат.

Обновление - добавление дополнительных данных

Спасибо @danblack за предложение добавить больше данных, чтобы сделать его проверяемым примером.

Моя текущая таблица

Node    ParentNode  EmployeeID  Depth   Lineage
100     NULL        1001        0       /
101     100         1002        NULL    NULL
102     101         1003        NULL    NULL
103     102         1004        NULL    NULL
104     102         1005        NULL    NULL
105     102         1006        NULL    NULL

Как это должно выглядеть после запуска сниппета

Node    ParentNode  EmployeeID  Depth   Lineage
100     NULL        1001        0       /
101     100         1002        1       /100/
102     101         1003        2       /100/101/
103     102         1004        3       /100/101/102/
104     102         1005        3       /100/101/102/
105     102         1006        3       /100/101/102/

@ danblack указал, что сниппетом является Microsoft SQL, а не MySQL, и он должен использоватьрекурсивный CTE, чтобы сделать это.Это моя попытка, но я до сих пор не могу понять.

;WITH user_count
AS
(
SELECT * FROM Tree WHERE Depth Is Null AS null_users
UNION ALL
WHILE EXISTS () 
UPDATE T SET T.depth = P.Depth + 1, 
T.Lineage = P.Lineage + Ltrim(Str(T.ParentNode,6,0)) + '/' 
FROM Tree AS T 
INNER JOIN Tree AS P ON (T.ParentNode=P.Node) 
WHERE P.Depth>=0 
AND P.Lineage Is Not Null 
AND T.Depth Is Null
)

1 Ответ

0 голосов
/ 08 февраля 2019

В MySQL-8.0:

select version();
| version() |
| :-------- |
| 8.0.13    |
CREATE TABLE tree (
  `Node` VARCHAR(3),
  `ParentNode` VARCHAR(3),
  `EmployeeID` INTEGER,
  `Depth` INTEGER,
  `Lineage` VARCHAR(16)
);
INSERT INTO tree
  (`Node`, `ParentNode`, `EmployeeID`, `Depth`, `Lineage`)
VALUES
  ('100', NULL, '1001', 0, '/'),
  ('101', '100', '1002', NULL, NULL),
  ('102', '101', '1003', NULL, NULL),
  ('103', '102', '1004', NULL, NULL),
  ('104', '102', '1005', NULL, NULL),
  ('105', '102', '1006', NULL, NULL);
WITH RECURSIVE prev AS (
SELECT * FROM tree WHERE ParentNode IS NULL
UNION
SELECT t.Node,t.ParentNode,t.EmployeeID,p.Depth + 1 as Depth, CONCAT(p.Lineage, t.ParentNode, '/')
FROM tree t
JOIN prev p ON t.ParentNode = p.Node
)
SELECT * FROM prev;
Node | ParentNode | EmployeeID | Depth | Lineage      
:--- | :--------- | ---------: | ----: | :------------
100  | <em>null</em>       |       1001 |     0 | /            
101  | 100        |       1002 |     1 | /100/        
102  | 101        |       1003 |     2 | /100/101/    
103  | 102        |       1004 |     3 | /100/101/102/
104  | 102        |       1005 |     3 | /100/101/102/
105  | 102        |       1006 |     3 | /100/101/102/
WITH RECURSIVE prev AS (
SELECT * FROM tree WHERE ParentNode IS NULL
UNION
SELECT t.Node,t.ParentNode,t.EmployeeID,p.Depth + 1 as Depth, CONCAT(p.Lineage, t.ParentNode, '/')
FROM prev p
JOIN tree t ON t.ParentNode = p.Node
)
UPDATE tree t, prev p
SET t.Depth=p.Depth, t.Lineage=p.Lineage
WHERE t.Node=p.Node;
SELECT * FROM tree
Node | ParentNode | EmployeeID | Depth | Lineage      
:--- | :--------- | ---------: | ----: | :------------
100  | <em>null</em>       |       1001 |     0 | /            
101  | 100        |       1002 |     1 | /100/        
102  | 101        |       1003 |     2 | /100/101/    
103  | 102        |       1004 |     3 | /100/101/102/
104  | 102        |       1005 |     3 | /100/101/102/
105  | 102        |       1006 |     3 | /100/101/102/

mysql8.0 дБ <> здесь fiddle

MariaDB еще не поддерживает UPDATE в CTE

Однако это может быть выполнено свременная таблица типа:

CREATE TEMPORARY TABLE newtree AS
WITH RECURSIVE prev AS (
SELECT * FROM tree WHERE ParentNode IS NULL
UNION
SELECT t.Node,t.ParentNode,t.EmployeeID,p.Depth + 1 as Depth, CONCAT(p.Lineage, t.ParentNode, '/')
FROM tree t JOIN prev p ON t.ParentNode = p.Node
)
SELECT Node,Depth,Lineage FROM prev;
UPDATE tree t, newtree p SET t.Depth=p.Depth, t.Lineage=p.Lineage WHERE t.Node=p.Node;
SELECT * from tree
Node | ParentNode | EmployeeID | Depth | Lineage      
:--- | :--------- | ---------: | ----: | :------------
100  | <em>null</em>       |       1001 |     0 | /            
101  | 100        |       1002 |     1 | /100/        
102  | 101        |       1003 |     2 | /100/101/    
103  | 102        |       1004 |     3 | /100/101/102/
104  | 102        |       1005 |     3 | /100/101/102/
105  | 102        |       1006 |     3 | /100/101/102/

MariaDB-10,3 дБ <> скрипка здесь

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