Say У меня есть стартовый стол (производный), который, как это ...MySQL рекурсивного автообъединение пересекающихся столбцы
-------------------------------------------------------
| UsergroupID | ParentID | PermissionIDs |
-------------------------------------------------------
| 1 | 0 | 1 |
| 1 | 0 | 2 |
| 1 | 0 | 3 |
| 1 | 0 | 4 |
| 1 | 0 | 5 |
| 1 | 0 | 6 |
| 2 | 1 | 1 |
| 2 | 1 | 8 |
| 2 | 1 | 9 |
| 3 | 1 | 3 |
| 3 | 1 | 8 |
| 3 | 1 | 2 |
-------------------------------------------------------
и я ищу, чтобы получить конечный результирующий набор, который выглядит следующим образом
-------------------------------------------------------
| UsergroupID | ParentID | PermissionID |
-------------------------------------------------------
| 1 | 0 | 1 |
| 1 | 0 | 2 |
| 1 | 0 | 3 |
| 1 | 0 | 4 |
| 1 | 0 | 5 |
| 1 | 0 | 6 |
| 2 | 1 | 1 |
| 3 | 1 | 3 |
| 3 | 1 | 2 |
-------------------------------------------------------
который в основном выполняет рекурсивный поиск родительского идентификатора и затем пересекает (внутреннее соединение) значения в столбце PermissionID. Таким образом, у ребенка никогда не будет больше разрешений, чем у родителя.
Я искал информацию о пользовательских функциях (думаю, я мог бы обернуть udf вокруг столбца и пересечь рекурсивно на основе родительского идентификатора), но это не привело меня далеко. Единственное, о чем я могу думать, это не делать это db, а делать это с кодом на стороне сервера.
Solarflare - вот что я только что пробовал использовать ваш скрипт ... это сработало!
delimiter $$
CREATE PROCEDURE prcPermCleanup5()
BEGIN
DROP TABLE IF EXISTS table1;
CREATE TABLE table1 (usergroupID INT, parentID INT, StoreID INT) ENGINE=MEMORY;
INSERT INTO table1 VALUES
(1,0,1),
(1,0,2),
(1,0,3),
(1,0,4),
(2,1,1),
(2,1,2),
(2,0,5),
(3,2,2),
(3,2,7),
(4,1,1),
(4,1,2),
(5,4,1),
(5,4,8),
(6,2,1),
(6,2,6);
REPEAT
DELETE entry.*
FROM table1 entry
LEFT JOIN table1 parent
ON entry.parentID = parent.usergroupID
AND entry.`StoreID` = parent.StoreID
WHERE parent.usergroupID IS NULL
AND NOT entry.parentID = 0;
UNTIL row_count() = 0 END REPEAT;
SELECT * FROM table1;
END $$
delimiter ;
Вы открыты для нормализации данных и не имеют массив разрешений в столбце PermissionsID и вместо этого использовать другую таблицу, в которой перечислены эти разрешения? В большинстве случаев проблемы с ненормализованными данными усложняются, это хороший пример. И вы можете использовать вложенные наборы, хотя вы, вероятно, тоже можете использовать дерево (если вы повторяете свою функцию для рекурсии) – Solarflare
Я открыт для изменения формата данных и моего второго примера таблицы (3-я таблица в исходном сообщении) это тот, который отображает разрешения как строки, а не как конкатенированный столбец. Эта «таблица» также является производной таблицей. – Josh
О, да, это лучше, я думаю, что я пропустил точку «стартового стола». Итак, у вас есть таблица: вы хотите «очистить ее» (удалить или пометить «неправильные» записи) или вы хотите сохранить «неправильные» записи и получить запрос, который возвращает этот более чистый список? Я думаю, что оба они не могут быть выполнены за один шаг, но один из них будет запросом, который вы должны выполнить n раз (n = глубина вашего дерева - 1 или пока ничего не изменится), второй, наверное, требуется временная таблица (вы можете сделать это в хранимой процедуре/udf). – Solarflare