重构 MySQL 查询
Refactoring MySQL query
我们提出了这个查询:
SELECT tn1.* FROM tree_node tn1
WHERE tn1.type != "folder" AND tn1.parent IN (
SELECT tn.id FROM tree_node tn
LEFT JOIN tree_node_access tna ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
) OR tn1.id IN (
SELECT tn.id FROM tree_node tn
LEFT JOIN tree_node_access tna ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
)
但必须有可能不必重复子查询两次,因为该查询完全相同。
有没有办法重构这个查询?
您可以将 or 替换为 UNION,将子查询替换为 JOIN:
SELECT tn1.*
FROM tree_node tn1
INNER JOIN tree_node tn
ON tn1.parent=tn.id
LEFT JOIN tree_node_access tna
ON tna.tree_node_id = tn.id
WHERE tn1.type != 'folder'
AND (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
UNION
SELECT tn1.*
FROM tree_node tn1
INNER JOIN tree_node tn
ON tn.id=tn1.id
LEFT JOIN tree_node_access tna
ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
您没有说明您使用的 MySQL 版本。在 MySQL 8.x 中,您可以为其使用 CTE(通用 Table 表达式)。
例如:
with
a as (
SELECT tn.id FROM tree_node tn
LEFT JOIN tree_node_access tna ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0
AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
)
SELECT tn1.* FROM tree_node tn1
WHERE tn1.type != "folder" AND tn1.parent IN (select id from a)
OR tn1.id IN (select id from a)
我们提出了这个查询:
SELECT tn1.* FROM tree_node tn1
WHERE tn1.type != "folder" AND tn1.parent IN (
SELECT tn.id FROM tree_node tn
LEFT JOIN tree_node_access tna ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
) OR tn1.id IN (
SELECT tn.id FROM tree_node tn
LEFT JOIN tree_node_access tna ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
)
但必须有可能不必重复子查询两次,因为该查询完全相同。
有没有办法重构这个查询?
您可以将 or 替换为 UNION,将子查询替换为 JOIN:
SELECT tn1.*
FROM tree_node tn1
INNER JOIN tree_node tn
ON tn1.parent=tn.id
LEFT JOIN tree_node_access tna
ON tna.tree_node_id = tn.id
WHERE tn1.type != 'folder'
AND (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
UNION
SELECT tn1.*
FROM tree_node tn1
INNER JOIN tree_node tn
ON tn.id=tn1.id
LEFT JOIN tree_node_access tna
ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0 AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
您没有说明您使用的 MySQL 版本。在 MySQL 8.x 中,您可以为其使用 CTE(通用 Table 表达式)。
例如:
with
a as (
SELECT tn.id FROM tree_node tn
LEFT JOIN tree_node_access tna ON tna.tree_node_id = tn.id
WHERE (tn.project_id = 50 AND tna.access = 0
AND (tna.user_id = 8 OR tna.user_group_id IN (26)))
)
SELECT tn1.* FROM tree_node tn1
WHERE tn1.type != "folder" AND tn1.parent IN (select id from a)
OR tn1.id IN (select id from a)