提问人:Tomas Novak 提问时间:2/22/2023 最后编辑:user1191247Tomas Novak 更新时间:2/24/2023 访问量:68
MySQL通过子验证父母
MySQL validating parents by children
问:
我在 Visual Studio 中编程,但我需要在 mySQL (v8.0.28) 表上执行验证,我想如果它在服务器上作为过程执行会更快。不幸的是,我的MySQL编程技能非常有限。
这相当于我的表格:
节点 ID | 节点级别 | 节点父级 | 节点值 | 节点有效 |
---|---|---|---|---|
0 | 0 | 根 | 零 | 0 |
1 | 1 | 0 | 零 | 0 |
2 | 2 | 1 | 零 | 0 |
3 | 3 | 2 | 2023-03-03 | 1 |
4 | 0 | 根 | 零 | 0 |
5 | 1 | 4 | 零 | 0 |
6 | 2 | 5 | 零 | 0 |
7 | 3 | 6 | 2023-03-03 | 1 |
8 | 0 | 根 | 零 | 0 |
9 | 1 | 8 | 零 | 0 |
10 | 1 | 8 | 零 | 0 |
它的工作方式类似于 Treeview 节点,我能够通过以下行验证底层节点的状态:
UPDATE `bs`.`valitable`
SET `NodeValid`='1'
WHERE `NodeLevel`='3' AND `NodeValue` > '2023-02-22';
我如何遍历 ='2' 的节点,因为我需要检查是否所有子项都有效 = 1(然后父项有效 = 1),否则父项有效 = 0。NodeLevel
我发现了一些时间......DO、FOR 循环、游标,但我无法编写正确的语法来正确执行此操作。或者 - 有没有其他方法可以做到这一点?
我尝试在Visual Studio中执行此操作,但它太慢了,因为它需要加载整个表,继续并保存回来。随着表的增长,它无法使用,所以我希望mySQL过程可以加快该过程,因为它可以直接从服务器运行。
答:
您应该更改表,以便使用 NodeParent 而不是 .无论如何,这是从 NodeParent 到 NodeID 的 FK 约束所必需的,您应该具备这些约束。NULL
root
这种方法使用递归 cte 来构建叶节点 () 及其所有祖先的完整列表。因此,根据您的描述,如果所有相关的叶节点都有效,我们可以将所有祖先更新为有效():NodeLevel = 3
NodeValue > '2023-02-22'
WITH RECURSIVE cte (AncestorID, LeafID) AS (
SELECT NodeParent, NodeID
FROM valitable WHERE NodeLevel = 3
UNION ALL
SELECT v.NodeParent, c.LeafID
FROM valitable v
JOIN cte c ON v.NodeID = c.AncestorID AND v.NodeParent IS NOT NULL
)
UPDATE valitable a
JOIN (
SELECT cte.AncestorID, MIN(l.NodeValue > '2023-02-22') valid
FROM cte
JOIN valitable l ON cte.LeafID = l.NodeID
GROUP BY cte.AncestorID
) j ON a.NodeID = j.AncestorID
SET a.NodeValid = j.valid;
为此,您需要按预期工作,您需要先运行 NodeLevel 3 节点的初始更新。
这不会对与 NodeLevel 3 节点没有关系的节点进行任何更改,因为没有对这些节点的规则进行解释。
更新
要设置节点与 NodeLevel 3 节点无关的位置,您可以在 update 语句中更改 to,但您需要确保它仅在 NodeLevel < 3 的地方更新,否则它将包含所有 NodeLevel 3 节点,因为它们未作为祖先包含在 cte 中:NodeValid = NULL
JOIN
LEFT JOIN
NULL
-- start with your initial update
UPDATE valitable
SET NodeValid = NodeValue > '2023-02-22' -- 1 if meets criterion, 0 if not
WHERE NodeLevel = 3;
WITH RECURSIVE cte (AncestorID, LeafID) AS (
SELECT NodeParent, NodeID
FROM valitable WHERE NodeLevel = 3
UNION ALL
SELECT v.NodeParent, c.LeafID
FROM valitable v
JOIN cte c ON v.NodeID = c.AncestorID AND v.NodeParent IS NOT NULL
)
UPDATE valitable a
LEFT JOIN (
SELECT cte.AncestorID, MIN(l.NodeValue > '2023-02-22') valid
FROM cte
JOIN valitable l ON cte.LeafID = l.NodeID
GROUP BY cte.AncestorID
) j ON a.NodeID = j.AncestorID
SET a.NodeValid = j.valid
WHERE a.NodeLevel < 3;
评论
UPDATE table SET NodeValid=1 WHERE NodeLevel=3 AND NodeValue > 2023-02-22;